@cavuno/board 1.25.0 → 1.26.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.
Files changed (37) hide show
  1. package/README.md +88 -0
  2. package/dist/bin.mjs +67 -34
  3. package/dist/filters.d.mts +55 -0
  4. package/dist/filters.d.ts +55 -0
  5. package/dist/filters.js +193 -0
  6. package/dist/filters.mjs +170 -0
  7. package/dist/format.d.mts +240 -0
  8. package/dist/format.d.ts +240 -0
  9. package/dist/format.js +453 -0
  10. package/dist/format.mjs +430 -0
  11. package/dist/index.d.mts +79 -3838
  12. package/dist/index.d.ts +79 -3838
  13. package/dist/index.js +154 -7
  14. package/dist/index.mjs +151 -4
  15. package/dist/jobs-CM67_J6H.d.mts +3836 -0
  16. package/dist/jobs-CM67_J6H.d.ts +3836 -0
  17. package/dist/theme.d.mts +63 -0
  18. package/dist/theme.d.ts +63 -0
  19. package/dist/theme.js +149 -0
  20. package/dist/theme.mjs +128 -0
  21. package/package.json +37 -2
  22. package/skills/cavuno-board-account/SKILL.md +147 -0
  23. package/skills/cavuno-board-applications/SKILL.md +110 -0
  24. package/skills/cavuno-board-blog/SKILL.md +99 -0
  25. package/skills/cavuno-board-companies/SKILL.md +99 -0
  26. package/skills/cavuno-board-filters/SKILL.md +89 -0
  27. package/skills/cavuno-board-format/SKILL.md +104 -0
  28. package/skills/cavuno-board-job-alerts/SKILL.md +115 -0
  29. package/skills/cavuno-board-job-posting/SKILL.md +130 -0
  30. package/skills/cavuno-board-jobs/SKILL.md +15 -0
  31. package/skills/cavuno-board-messaging/SKILL.md +121 -0
  32. package/skills/cavuno-board-paywall/SKILL.md +108 -0
  33. package/skills/cavuno-board-salaries/SKILL.md +87 -0
  34. package/skills/cavuno-board-setup/SKILL.md +26 -2
  35. package/skills/cavuno-board-smoke-test/SKILL.md +84 -0
  36. package/skills/cavuno-board-theme/SKILL.md +69 -0
  37. package/skills/manifest.json +92 -1
@@ -0,0 +1,3836 @@
1
+ interface components {
2
+ schemas: {
3
+ AccessCheckoutBody: {
4
+ /**
5
+ * @description The offer tier to purchase (from `GET /paywall/offers/enabled`).
6
+ * @enum {string}
7
+ */
8
+ offerKey: "daily" | "weekly" | "monthly" | "quarterly" | "yearly" | "lifetime";
9
+ /** @description Relative path Stripe returns the buyer to on completion; `session_id` is appended. */
10
+ returnPath: string;
11
+ /** @enum {string} */
12
+ colorMode: "light" | "dark";
13
+ };
14
+ AccessCheckoutSession: {
15
+ /** @enum {string} */
16
+ object: "checkout_session";
17
+ sessionId: string;
18
+ /** @description The Checkout Session client secret to mount the embedded form. */
19
+ clientSecret: string;
20
+ /** @description The board’s connected Stripe account to initialise Stripe.js with. */
21
+ stripeAccountId: string;
22
+ /** @description The platform Stripe publishable key for `loadStripe`. */
23
+ publishableKey: string;
24
+ /**
25
+ * @description `recurring` grants get a manage-subscription portal; `lifetime` do not.
26
+ * @enum {string}
27
+ */
28
+ offerType: "recurring" | "lifetime";
29
+ };
30
+ AccessCheckoutSessionState: {
31
+ /** @enum {string} */
32
+ object: "checkout_session_state";
33
+ /** @enum {string} */
34
+ status: "open" | "complete" | "expired";
35
+ clientSecret: string | null;
36
+ };
37
+ AccessGrant: {
38
+ /** @enum {string} */
39
+ object: "access_grant";
40
+ hasAccess: boolean;
41
+ /** @enum {string|null} */
42
+ status: "active" | "past_due" | "unpaid" | "incomplete" | "incomplete_expired" | "canceled" | "pending" | null;
43
+ /** @enum {string|null} */
44
+ offerType: "recurring" | "lifetime" | null;
45
+ offerKey: string | null;
46
+ currentPeriodEnd: string | null;
47
+ cancelAtPeriodEnd: boolean;
48
+ };
49
+ AccessPortalBody: {
50
+ /** @description Relative path Stripe returns the buyer to; defaults to the board root. */
51
+ returnPath?: string;
52
+ };
53
+ AccessPortalSession: {
54
+ /** @enum {string} */
55
+ object: "portal_session";
56
+ /** Format: uri */
57
+ url: string;
58
+ };
59
+ AddApplicantNoteBody: {
60
+ /** @description The note text. */
61
+ body: string;
62
+ };
63
+ /** @description Links related to this resource. List responses only carry the `admin` URL because the public URL needs the company slug, which list-shape Convex projections do not fan out to. */
64
+ AdminOnlyResourceLinks: {
65
+ /**
66
+ * Format: uri
67
+ * @description URL inside the Cavuno app where the authenticated owner can manage this resource.
68
+ */
69
+ admin: string;
70
+ };
71
+ Alert: {
72
+ /** @description Job-alert preference ID — also the path key. */
73
+ id: string;
74
+ /** @enum {string} */
75
+ object: "alert";
76
+ label: string | null;
77
+ /** @enum {string} */
78
+ frequency: "daily" | "weekly";
79
+ isActive: boolean;
80
+ filters: {
81
+ jobFunctions: string[];
82
+ seniorityLevels: string[];
83
+ remoteOptions: string[];
84
+ placeIds: string[];
85
+ salaryMin: number | null;
86
+ salaryMax: number | null;
87
+ salaryCurrency: string | null;
88
+ };
89
+ /**
90
+ * Format: date-time
91
+ * @description When this alert last dispatched a digest, or null.
92
+ */
93
+ lastSentAt: string | null;
94
+ };
95
+ AlertBody: {
96
+ label?: string;
97
+ /** @enum {string} */
98
+ frequency: "daily" | "weekly";
99
+ jobFunctions?: string[];
100
+ seniorityLevels?: string[];
101
+ remoteOptions?: string[];
102
+ placeIds?: string[];
103
+ salaryMin?: number | null;
104
+ salaryMax?: number | null;
105
+ salaryCurrency?: string | null;
106
+ };
107
+ ApiKey: {
108
+ /** @description Unique identifier for the object. */
109
+ id: string;
110
+ /**
111
+ * @description String representing the object's type. Objects of the same type share the same value.
112
+ * @enum {string}
113
+ */
114
+ object: "api_key";
115
+ /** @description Public key ID component, embedded in the key prefix as `cavuno_live_<keyId>_`. */
116
+ keyId: string;
117
+ /** @description Human-readable name for the key, shown in the dashboard. */
118
+ name: string;
119
+ /** @description Public prefix in the form `cavuno_live_<keyId>_`. Safe to log; the full plaintext secret is never returned by the API. */
120
+ prefix: string;
121
+ /** @description Time at which the key was created. Unix epoch in milliseconds. */
122
+ createdAt: number;
123
+ /** @description Identifier of the user who minted the key. */
124
+ createdBy: string;
125
+ /** @description Time at which the key was last used to authenticate a request, or `null` if it has never been used. Unix epoch in milliseconds. */
126
+ lastUsedAt: number | null;
127
+ /** @description Time at which the key was revoked, or `null` if the key is still active. Unix epoch in milliseconds. */
128
+ revokedAt: number | null;
129
+ /** @description Time at which the key expires, or `null` if the key has no expiry. Unix epoch in milliseconds. */
130
+ expiresAt: number | null;
131
+ };
132
+ Application: {
133
+ /** @description Application ID — the `:applicationId` path key. */
134
+ id: string;
135
+ /** @enum {string} */
136
+ object: "application";
137
+ /**
138
+ * @description Coarse candidate-facing status derived from the employer pipeline stage.
139
+ * @enum {string}
140
+ */
141
+ status: "applied" | "interviewing" | "negotiation" | "hired" | "archived";
142
+ /** Format: date-time */
143
+ appliedAt: string;
144
+ /** Format: date-time */
145
+ updatedAt: string;
146
+ coverNote: string | null;
147
+ candidateName: string | null;
148
+ candidateEmail: string | null;
149
+ candidateLocation: string | null;
150
+ candidateHeadline: string | null;
151
+ resumeFilename: string | null;
152
+ job: {
153
+ id: string;
154
+ title: string;
155
+ slug: string | null;
156
+ companySlug: string | null;
157
+ companyName: string | null;
158
+ } | null;
159
+ };
160
+ ApplyBody: {
161
+ name?: string;
162
+ /** Format: email */
163
+ email?: string;
164
+ coverNote?: string;
165
+ };
166
+ AuditLogEntry: {
167
+ /** @description Unique identifier for the object. */
168
+ id: string;
169
+ /**
170
+ * @description String representing the object's type. Objects of the same type share the same value.
171
+ * @enum {string}
172
+ */
173
+ object: "audit_log";
174
+ /** @description Identifier of the account the entry belongs to. */
175
+ accountId: string;
176
+ /**
177
+ * @description Type of actor that performed the action.
178
+ * @enum {string}
179
+ */
180
+ actorType: "api_key" | "oauth_token" | "user_session" | "system";
181
+ /** @description Identifier of the actor that performed the action. */
182
+ actorId: string;
183
+ /** @description Human-readable label for the actor, suitable for display. */
184
+ actorLabel: string;
185
+ /** @description Action that was performed (e.g. `jobs.create`, `companies.update`). */
186
+ action: string;
187
+ /** @description Type of resource the action was performed on. */
188
+ resourceType: string;
189
+ /** @description Identifier of the resource the action was performed on, or `null` for resource-less actions. */
190
+ resourceId: string | null;
191
+ /** @description Serialized JSON snapshot of the resource before the action, or `null` for create actions. */
192
+ before: string | null;
193
+ /** @description Serialized JSON snapshot of the resource after the action, or `null` for delete actions. */
194
+ after: string | null;
195
+ /** @description Serialized JSON of free-form metadata about the action (e.g. truncation byte sizes), or `null` if none was attached. */
196
+ metadata: string | null;
197
+ /** @description IP address the request originated from, or `null` if unavailable. */
198
+ ipAddress: string | null;
199
+ /** @description User-agent string from the request, or `null` if unavailable. */
200
+ userAgent: string | null;
201
+ /** @description Identifier of the request that produced the entry. Use this to correlate with platform logs. */
202
+ requestId: string;
203
+ /** @description Time at which the audit entry was written. Unix epoch in milliseconds. */
204
+ timestamp: number;
205
+ };
206
+ BatchRequestBody: {
207
+ /** @description Array of sub-operations to execute. Each entry runs independently and reports its result on the corresponding entry of the response `data` array. Sub-operation `id` values must be unique within the batch. Up to 100 entries. */
208
+ operations: ({
209
+ id: string;
210
+ /** @enum {string} */
211
+ method: "POST";
212
+ body?: unknown;
213
+ action?: string;
214
+ resourceId?: string;
215
+ } | {
216
+ id: string;
217
+ /** @enum {string} */
218
+ method: "PATCH";
219
+ body?: unknown;
220
+ resourceId: string;
221
+ } | {
222
+ id: string;
223
+ /** @enum {string} */
224
+ method: "DELETE";
225
+ resourceId: string;
226
+ })[];
227
+ };
228
+ Block: {
229
+ /** @enum {string} */
230
+ object: "block";
231
+ /** @enum {boolean} */
232
+ blocked: true;
233
+ };
234
+ BlockStatus: {
235
+ /** @enum {string} */
236
+ object: "block_status";
237
+ blocked: boolean;
238
+ };
239
+ BlockUserBody: {
240
+ boardUserId: string;
241
+ };
242
+ BlockedUser: {
243
+ id: string;
244
+ /** @enum {string} */
245
+ object: "blocked_user";
246
+ boardUserId: string;
247
+ displayName: string;
248
+ avatarUrl: string | null;
249
+ /** Format: date-time */
250
+ createdAt: string;
251
+ };
252
+ BlogAuthor: {
253
+ /** @description Unique identifier for the object. Use this value as the `{id}` path parameter for the author endpoints (e.g. `GET /v1/blog/authors/{id}`). */
254
+ id: string;
255
+ /**
256
+ * @description String representing the object's type. Objects of the same type share the same value.
257
+ * @enum {string}
258
+ */
259
+ object: "blog_author";
260
+ /** @description Display name of the author. */
261
+ name: string;
262
+ /** @description URL-friendly slug for the author. */
263
+ slug: string;
264
+ /** @description Short biography, or `null` if not set. */
265
+ bio: string | null;
266
+ /** @description The author's email address, or `null` if not set. */
267
+ email: string | null;
268
+ /** @description Author visibility status, or `null` if not set. */
269
+ status: string | null;
270
+ /** @description URL of the author avatar, or `null` if no avatar is set. */
271
+ avatarUrl: string | null;
272
+ /** @description The author's website URL, or `null` if not set. */
273
+ websiteUrl: string | null;
274
+ /** @description The author's X (Twitter) URL, or `null` if not set. */
275
+ twitterUrl: string | null;
276
+ /** @description The author's LinkedIn URL, or `null` if not set. */
277
+ linkedinUrl: string | null;
278
+ /** @description The author's GitHub URL, or `null` if not set. */
279
+ githubUrl: string | null;
280
+ /** @description SEO meta title, or `null` if not set. */
281
+ metaTitle: string | null;
282
+ /** @description SEO meta description, or `null` if not set. */
283
+ metaDescription: string | null;
284
+ /** @description Time at which the author was created. ISO 8601 datetime. */
285
+ createdAt: string;
286
+ /** @description Time at which the author was last updated, or `null` if it has never been updated. ISO 8601 datetime. */
287
+ updatedAt: string | null;
288
+ };
289
+ BlogPost: components["schemas"]["BlogPostSummary"] & {
290
+ html: string | null;
291
+ };
292
+ BlogPostSummary: {
293
+ /** @description Unique identifier for the object. Use this value as the `{id}` path parameter for the blog-post endpoints (e.g. `GET /v1/blog/posts/{id}`). */
294
+ id: string;
295
+ /** @enum {string} */
296
+ object: "blog_post";
297
+ title: string;
298
+ slug: string;
299
+ status: string;
300
+ visibility: string;
301
+ type: string;
302
+ featured: boolean;
303
+ authorIds: string[];
304
+ tagIds: string[];
305
+ coverUrl: string | null;
306
+ ogImageUrl: string | null;
307
+ featureImageAlt: string | null;
308
+ featureImageCaption: string | null;
309
+ customExcerpt: string | null;
310
+ readingTimeMin: number | null;
311
+ seoTitle: string | null;
312
+ seoDescription: string | null;
313
+ canonicalUrl: string | null;
314
+ publishedAt: string | null;
315
+ createdAt: string;
316
+ updatedAt: string | null;
317
+ };
318
+ BlogPostsBatchRequest: {
319
+ /** @description Array of post sub-operations to execute. Each runs independently and reports on the matching entry of the response `data` array. `id` values must be unique. Supported: POST (create), PATCH (update), DELETE, and POST with action `publish`/`unpublish`. Up to 50 entries. */
320
+ operations: ({
321
+ id: string;
322
+ /** @enum {string} */
323
+ method: "POST";
324
+ body?: unknown;
325
+ action?: string;
326
+ resourceId?: string;
327
+ } | {
328
+ id: string;
329
+ /** @enum {string} */
330
+ method: "PATCH";
331
+ body?: unknown;
332
+ resourceId: string;
333
+ } | {
334
+ id: string;
335
+ /** @enum {string} */
336
+ method: "DELETE";
337
+ resourceId: string;
338
+ })[];
339
+ };
340
+ BlogTag: {
341
+ /** @description Unique identifier for the object. Use this value as the `{id}` path parameter for the tag endpoints (e.g. `GET /v1/blog/tags/{id}`). */
342
+ id: string;
343
+ /**
344
+ * @description String representing the object's type. Objects of the same type share the same value.
345
+ * @enum {string}
346
+ */
347
+ object: "blog_tag";
348
+ /** @description Display name of the tag. */
349
+ name: string;
350
+ /** @description URL-friendly slug for the tag. */
351
+ slug: string;
352
+ /** @description Tag description, or `null` if not set. */
353
+ description: string | null;
354
+ /** @description Tag visibility, or `null` if not set. */
355
+ visibility: string | null;
356
+ /** @description SEO meta title, or `null` if not set. */
357
+ metaTitle: string | null;
358
+ /** @description SEO meta description, or `null` if not set. */
359
+ metaDescription: string | null;
360
+ /** @description Time at which the tag was created. ISO 8601 datetime. */
361
+ createdAt: string;
362
+ /** @description Time at which the tag was last updated, or `null` if it has never been updated. ISO 8601 datetime. */
363
+ updatedAt: string | null;
364
+ };
365
+ BoardAccessGrant: {
366
+ /** @enum {string} */
367
+ object: "board_access_grant";
368
+ /** @description The board-access grant. Send it as the `X-Board-Access` header on subsequent content reads to pass the password wall. */
369
+ token: string;
370
+ };
371
+ BoardAuthConsumeMagicLinkBody: {
372
+ token: string;
373
+ };
374
+ BoardAuthForgotPasswordBody: {
375
+ /** Format: email */
376
+ email: string;
377
+ };
378
+ BoardAuthLoginBody: {
379
+ /** Format: email */
380
+ email: string;
381
+ password: string;
382
+ };
383
+ BoardAuthLogoutBody: {
384
+ refreshToken: string;
385
+ };
386
+ BoardAuthOAuthAuthorizationUrl: {
387
+ /** @enum {string} */
388
+ object: "oauth_authorization_url";
389
+ /** @enum {string} */
390
+ provider: "google" | "linkedin";
391
+ /** Format: uri */
392
+ authorizeUrl: string;
393
+ };
394
+ BoardAuthOAuthExchangeBody: {
395
+ token: string;
396
+ };
397
+ BoardAuthRefreshBody: {
398
+ refreshToken: string;
399
+ };
400
+ BoardAuthRegisterBody: {
401
+ /**
402
+ * @description Which role profile to create on the board.
403
+ * @enum {string}
404
+ */
405
+ role: "candidate" | "employer";
406
+ /**
407
+ * @description Registration method. Only `emailpass` is supported.
408
+ * @enum {string}
409
+ */
410
+ method: "emailpass";
411
+ /** Format: email */
412
+ email: string;
413
+ /** @description Minimum 8 characters. */
414
+ password: string;
415
+ displayName: string;
416
+ };
417
+ BoardAuthRequestMagicLinkBody: {
418
+ /** Format: email */
419
+ email: string;
420
+ /** @description Optional same-origin path to carry through the email link. */
421
+ returnTo?: string;
422
+ };
423
+ BoardAuthResetPasswordBody: {
424
+ token: string;
425
+ /** @description Minimum 8 characters. */
426
+ password: string;
427
+ };
428
+ BoardAuthSession: {
429
+ /** @enum {string} */
430
+ object: "board_auth_session";
431
+ /** @description Short-lived JWT (1 hour). Send as `Authorization: Bearer`. */
432
+ accessToken: string;
433
+ /** @description Opaque single-use refresh token (30 days). Each refresh returns a replacement; a reused token is rejected. */
434
+ refreshToken: string;
435
+ /** @description Access-token expiry, epoch milliseconds. */
436
+ expiresAt: number;
437
+ boardUser: components["schemas"]["BoardUser"];
438
+ };
439
+ BoardAuthVerifyEmailBody: {
440
+ token: string;
441
+ };
442
+ BoardSeo: {
443
+ /** @enum {string} */
444
+ object: "board_seo";
445
+ /** @description Verbatim `ads.txt` content, or `null` when not configured. */
446
+ adsTxt: string | null;
447
+ /** @description IndexNow key-file content, or `null` when not configured. */
448
+ indexNowKey: string | null;
449
+ /** @description Google site-verification token for the `<meta>` tag, or `null`. */
450
+ googleSiteVerification: string | null;
451
+ /**
452
+ * Format: uri
453
+ * @description The board's canonical base URL (honours a configured custom domain). Build `robots.txt`'s `Sitemap:` line (`${canonicalBase}/sitemap.xml`) and canonical links from it.
454
+ */
455
+ canonicalBase: string;
456
+ /** @description Absolute URLs for the board's configured favicons / app icons (null when unset). The variant key implies the role + size; build `<link rel="icon">` tags + the web-manifest icon list from these. */
457
+ icons: {
458
+ ico: string | null;
459
+ svg: string | null;
460
+ appleTouch: string | null;
461
+ icon192: string | null;
462
+ icon512: string | null;
463
+ iconMaskable512: string | null;
464
+ };
465
+ /** @description Web-manifest metadata; assemble `site.webmanifest` from this + `icons`. */
466
+ manifest: {
467
+ name: string;
468
+ themeColor: string;
469
+ };
470
+ };
471
+ BoardUser: {
472
+ /** @description Board user ID. */
473
+ id: string;
474
+ /** @enum {string} */
475
+ object: "board_user";
476
+ /** @enum {string} */
477
+ role: "candidate" | "employer";
478
+ email: string;
479
+ displayName: string | null;
480
+ emailVerified: boolean;
481
+ };
482
+ BulkMoveApplicantsBody: {
483
+ applicationIds: string[];
484
+ /** @description The target stage id. */
485
+ stageId: string;
486
+ };
487
+ BulkRejectApplicantsBody: {
488
+ applicationIds: string[];
489
+ };
490
+ CandidateAvatar: {
491
+ /** @enum {string} */
492
+ object: "candidate_avatar";
493
+ avatarUrl: string | null;
494
+ };
495
+ CandidateEducation: {
496
+ id: string;
497
+ /** @enum {string} */
498
+ object: "candidate_education";
499
+ institutionName: string;
500
+ institutionUrl: string | null;
501
+ degree: string | null;
502
+ fieldOfStudy: string | null;
503
+ grade: string | null;
504
+ activitiesAndSocieties: string | null;
505
+ startDate: string | null;
506
+ endDate: string | null;
507
+ description: string | null;
508
+ sortOrder: number;
509
+ };
510
+ CandidateExperience: {
511
+ id: string;
512
+ /** @enum {string} */
513
+ object: "candidate_experience";
514
+ title: string;
515
+ companyName: string;
516
+ companyUrl: string | null;
517
+ location: string | null;
518
+ employmentType: string | null;
519
+ locationType: string | null;
520
+ foundVia: string | null;
521
+ startDate: string;
522
+ endDate: string | null;
523
+ description: string | null;
524
+ sortOrder: number;
525
+ experienceSkills: string[];
526
+ };
527
+ CandidateLanguage: {
528
+ /** @enum {string} */
529
+ object: "candidate_language";
530
+ name: string;
531
+ proficiency: string;
532
+ };
533
+ CandidateProfile: {
534
+ id: string;
535
+ /** @enum {string} */
536
+ object: "candidate_profile";
537
+ displayName: string | null;
538
+ bio: string | null;
539
+ avatarUrl: string | null;
540
+ handle: string | null;
541
+ headline: string | null;
542
+ location: string | null;
543
+ /** @enum {string} */
544
+ profileVisibility: "hidden" | "logged_in_only" | "public";
545
+ /** @enum {string} */
546
+ jobSearchStatus: "actively_looking" | "open_to_offers" | "not_looking";
547
+ /** @enum {string} */
548
+ jobSearchStatusVisibleTo: "everyone" | "employers_only";
549
+ openToRelocate: boolean;
550
+ };
551
+ CandidateSkill: {
552
+ /** @enum {string} */
553
+ object: "candidate_skill";
554
+ name: string;
555
+ jobSkillId: string | null;
556
+ };
557
+ ClaimableCompany: {
558
+ id: string;
559
+ /** @enum {string} */
560
+ object: "claimable_company";
561
+ name: string;
562
+ slug: string;
563
+ website: string | null;
564
+ };
565
+ CompaniesBatchRequest: {
566
+ /** @description Array of sub-operations to execute. Each entry runs independently and reports its result on the corresponding entry of the response `data` array. Sub-operation `id` values must be unique within the batch. Up to 100 entries. */
567
+ operations: ({
568
+ id: string;
569
+ /** @enum {string} */
570
+ method: "POST";
571
+ body?: unknown;
572
+ action?: string;
573
+ resourceId?: string;
574
+ } | {
575
+ id: string;
576
+ /** @enum {string} */
577
+ method: "PATCH";
578
+ body?: unknown;
579
+ resourceId: string;
580
+ } | {
581
+ id: string;
582
+ /** @enum {string} */
583
+ method: "DELETE";
584
+ resourceId: string;
585
+ })[];
586
+ };
587
+ Company: components["schemas"]["CompanySummary"] & {
588
+ /** @description Long-form description of the company, or `null` if not set. */
589
+ description: string | null;
590
+ /** @description Whether automated backfill of jobs from this company is supported, or `null` if not yet evaluated. */
591
+ canBackfill: boolean | null;
592
+ /** @description Total number of jobs at this company across all statuses. */
593
+ jobCount: number;
594
+ /** @description Number of currently-published jobs at this company. */
595
+ publishedJobCount: number;
596
+ };
597
+ CompanyCategorySalary: {
598
+ /** @enum {string} */
599
+ object: "company_category_salary";
600
+ categorySourceSlug: string;
601
+ categoryCanonicalSlug: string;
602
+ companyName: string;
603
+ companySlug: string;
604
+ companyLogoPath: string | null;
605
+ companyWebsite: string | null;
606
+ categoryName: string;
607
+ overallSalary: {
608
+ avgMin: number;
609
+ avgMax: number;
610
+ jobCount: number;
611
+ } | null;
612
+ bySeniority: {
613
+ seniority: string;
614
+ avgSalaryMin: number;
615
+ avgSalaryMax: number;
616
+ jobCount: number;
617
+ boardAvgMin: number | null;
618
+ boardAvgMax: number | null;
619
+ boardMedianMin: number | null;
620
+ boardMedianMax: number | null;
621
+ boardP25Min: number | null;
622
+ boardP75Min: number | null;
623
+ boardP25Max: number | null;
624
+ boardP75Max: number | null;
625
+ diffPercent: number | null;
626
+ }[];
627
+ competitors: {
628
+ companySlug: string;
629
+ companyName: string;
630
+ logoPath: string | null;
631
+ avgSalaryMin: number;
632
+ avgSalaryMax: number;
633
+ jobCount: number;
634
+ }[];
635
+ boardCategoryAvgMin: number | null;
636
+ boardCategoryAvgMax: number | null;
637
+ boardCategoryP25Min: number | null;
638
+ boardCategoryP75Max: number | null;
639
+ currency: string;
640
+ };
641
+ CompanyMarket: {
642
+ /** @enum {string} */
643
+ object: "company_market";
644
+ slug: string;
645
+ name: string;
646
+ /** @description Number of companies on the board in this market. */
647
+ companyCount: number;
648
+ };
649
+ CompanyMarketRef: {
650
+ /** @description Display name of the market. */
651
+ name: string;
652
+ /** @description Source slug for the market. Use it as the `:market` segment of the market-scoped company browse. */
653
+ slug: string;
654
+ };
655
+ CompanyMembership: {
656
+ id: string;
657
+ /** @enum {string} */
658
+ object: "company_membership";
659
+ /** @enum {string} */
660
+ status: "approved" | "pending_work_email" | "awaiting_admin" | "rejected";
661
+ role: string;
662
+ workEmail: string | null;
663
+ /** Format: date-time */
664
+ workEmailVerifiedAt: string | null;
665
+ company: {
666
+ id: string;
667
+ name: string;
668
+ slug: string | null;
669
+ website: string | null;
670
+ logoUrl: string | null;
671
+ };
672
+ };
673
+ CompanyPublic: {
674
+ /** @description Unique identifier for the object. Use this value as the `{id}` path parameter for the company endpoints (e.g. `GET /v1/companies/{id}`). */
675
+ id: string;
676
+ /**
677
+ * @description String representing the object's type. Objects of the same type share the same value.
678
+ * @enum {string}
679
+ */
680
+ object: "public_company";
681
+ /** @description Display name of the company. */
682
+ name: string;
683
+ /** @description URL-friendly slug for the company. */
684
+ slug: string;
685
+ /** @description Public company website URL, or `null` if not set. */
686
+ website: string | null;
687
+ /** @description URL of the company logo, or `null` if no logo is set. */
688
+ logoUrl: string | null;
689
+ /** @description Long-form description of the company, or `null` if not set. */
690
+ description: string | null;
691
+ /** @description Total number of public-facing jobs at this company. Currently mirrors `publishedJobCount`. */
692
+ jobCount: number;
693
+ /** @description Number of currently-published, non-expired jobs at this company. */
694
+ publishedJobCount: number;
695
+ links: components["schemas"]["PublicCompanyLinks"];
696
+ };
697
+ CompanyPublicDetail: components["schemas"]["CompanyPublic"] & {
698
+ /** @description Markets (sectors) this company operates in, each with its source slug. Empty when the company has no markets. */
699
+ markets: components["schemas"]["CompanyMarketRef"][];
700
+ };
701
+ CompanySalary: {
702
+ /** @enum {string} */
703
+ object: "company_salary";
704
+ companyName: string;
705
+ companySlug: string;
706
+ companyLogoPath: string | null;
707
+ companyWebsite: string | null;
708
+ overallSalary: {
709
+ avgMin: number;
710
+ avgMax: number;
711
+ jobCount: number;
712
+ } | null;
713
+ bySeniority: {
714
+ seniority: string;
715
+ avgSalaryMin: number;
716
+ avgSalaryMax: number;
717
+ jobCount: number;
718
+ boardAvgMin: number | null;
719
+ boardAvgMax: number | null;
720
+ boardMedianMin: number | null;
721
+ boardMedianMax: number | null;
722
+ boardP25Min: number | null;
723
+ boardP75Min: number | null;
724
+ boardP25Max: number | null;
725
+ boardP75Max: number | null;
726
+ diffPercent: number | null;
727
+ }[];
728
+ competitors: {
729
+ companySlug: string;
730
+ companyName: string;
731
+ logoPath: string | null;
732
+ avgSalaryMin: number;
733
+ avgSalaryMax: number;
734
+ jobCount: number;
735
+ }[];
736
+ topLocations: {
737
+ locationName: string;
738
+ countryCode: string;
739
+ placeSlug: string;
740
+ avgSalaryMin: number;
741
+ avgSalaryMax: number;
742
+ jobCount: number;
743
+ }[];
744
+ byCategory: {
745
+ categorySlug: string;
746
+ categoryName: string;
747
+ avgSalaryMin: number;
748
+ avgSalaryMax: number;
749
+ jobCount: number;
750
+ }[];
751
+ boardOverallAvgMin: number | null;
752
+ boardOverallAvgMax: number | null;
753
+ boardMedianMin: number | null;
754
+ boardMedianMax: number | null;
755
+ boardP25Min: number | null;
756
+ boardP75Min: number | null;
757
+ boardP25Max: number | null;
758
+ boardP75Max: number | null;
759
+ currency: string;
760
+ };
761
+ CompanySummary: {
762
+ /** @description Unique identifier for the object. Use this value as the `{id}` path parameter for the company endpoints (e.g. `GET /v1/companies/{id}`). */
763
+ id: string;
764
+ /**
765
+ * @description String representing the object's type. Objects of the same type share the same value.
766
+ * @enum {string}
767
+ */
768
+ object: "company";
769
+ /** @description Display name of the company. */
770
+ name: string;
771
+ /** @description URL-friendly slug for the company. */
772
+ slug: string;
773
+ /** @description Public company website URL, or `null` if not set. */
774
+ website: string | null;
775
+ /** @description URL of the company logo, or `null` if no logo is set. */
776
+ logoUrl: string | null;
777
+ /** @description One-line summary of the company, or `null` if not set. */
778
+ summary: string | null;
779
+ /** @description X (Twitter) profile URL, or `null` if not set. */
780
+ xUrl: string | null;
781
+ /** @description LinkedIn page URL, or `null` if not set. */
782
+ linkedinUrl: string | null;
783
+ /** @description Facebook page URL, or `null` if not set. */
784
+ facebookUrl: string | null;
785
+ /** @description Time at which the company was created. ISO 8601 datetime. */
786
+ createdAt: string;
787
+ /** @description Time at which the company was last updated, or `null` if it has never been updated. ISO 8601 datetime. */
788
+ updatedAt: string | null;
789
+ /** @description Public + admin URLs for this company. `public` may be `null` if the company lacks a slug. */
790
+ links: components["schemas"]["ResourceLinks"] & {
791
+ /**
792
+ * Format: uri
793
+ * @description Canonical public URL for this company on the board, or `null` when no slug is set.
794
+ */
795
+ public?: string | null;
796
+ };
797
+ };
798
+ ConfirmWorkEmailBody: {
799
+ token: string;
800
+ };
801
+ Conversation: {
802
+ id: string;
803
+ /** @enum {string} */
804
+ object: "conversation";
805
+ /** Format: date-time */
806
+ lastMessageAt: string;
807
+ lastMessageSnippet: string;
808
+ lastMessageAuthorBoardUserId: string;
809
+ /** Format: date-time */
810
+ archivedAt: string | null;
811
+ hasUnread: boolean;
812
+ counterparty: components["schemas"]["ConversationCounterparty"];
813
+ };
814
+ ConversationArchive: {
815
+ /** @enum {string} */
816
+ object: "conversation_archive";
817
+ /** Format: date-time */
818
+ archivedAt: string | null;
819
+ };
820
+ ConversationCounterparty: {
821
+ boardUserId: string;
822
+ displayName: string;
823
+ avatarUrl: string | null;
824
+ companyName: string | null;
825
+ handle: string | null;
826
+ companySlug: string | null;
827
+ };
828
+ ConversationDetail: components["schemas"]["Conversation"] & {
829
+ /** @enum {string} */
830
+ viewerRole: "employer" | "candidate";
831
+ viewerLastReadMessageId: string | null;
832
+ };
833
+ ConversationRef: {
834
+ /** @enum {string} */
835
+ object: "conversation_ref";
836
+ conversationId: string | null;
837
+ };
838
+ CreateAuthorBody: {
839
+ /** @description URL-friendly slug for the author. Auto-generated from `name` when omitted. */
840
+ slug?: string;
841
+ /** @description Short biography for the author. Sanitized HTML. */
842
+ bio?: string;
843
+ /**
844
+ * Format: email
845
+ * @description The author's email address.
846
+ */
847
+ email?: string;
848
+ /**
849
+ * @description Author visibility status. One of `active` or `inactive`.
850
+ * @enum {string}
851
+ */
852
+ status?: "active" | "inactive";
853
+ /** @description Storage ID of an uploaded avatar image (from `POST /v1/media/upload`). Pass `null` to clear an existing avatar. */
854
+ avatarStorageId?: string | null;
855
+ /** @description The author's personal website URL. Normalized to a canonical URL when stored. */
856
+ websiteUrl?: string;
857
+ /** @description The author's X (Twitter) profile URL. Stored as the canonical `https://x.com/<handle>` URL. */
858
+ twitterUrl?: string;
859
+ /** @description The author's LinkedIn profile URL. */
860
+ linkedinUrl?: string;
861
+ /** @description The author's GitHub profile URL. */
862
+ githubUrl?: string;
863
+ /** @description SEO meta title for the author page. */
864
+ metaTitle?: string;
865
+ /** @description SEO meta description for the author page. */
866
+ metaDescription?: string;
867
+ /** @description The author's display name. */
868
+ name: string;
869
+ };
870
+ CreateBlogPostBody: {
871
+ slug?: string;
872
+ html?: string;
873
+ customExcerpt?: string;
874
+ readingTimeMin?: number;
875
+ featured?: boolean;
876
+ authorIds?: string[];
877
+ tagIds?: string[];
878
+ coverStorageId?: string | null;
879
+ ogImageStorageId?: string | null;
880
+ featureImageAlt?: string;
881
+ featureImageCaption?: string;
882
+ seoTitle?: string;
883
+ seoDescription?: string;
884
+ /** Format: uri */
885
+ canonicalUrl?: string;
886
+ /** Format: date-time */
887
+ publishedAt?: string;
888
+ title: string;
889
+ /** @enum {string} */
890
+ status?: "draft" | "scheduled" | "published";
891
+ };
892
+ CreateCompanyBody: {
893
+ /** @description Public company website URL. Normalized to a canonical apex domain when stored. */
894
+ website?: string;
895
+ /** @description One-line summary of the company. Up to 280 characters. */
896
+ summary?: string;
897
+ /** @description Long-form description of the company. Up to 25,000 characters. */
898
+ description?: string;
899
+ /** @description X (Twitter) profile URL or handle. Stored as the canonical handle. */
900
+ xUrl?: string;
901
+ /** @description LinkedIn company page URL. */
902
+ linkedinUrl?: string;
903
+ /** @description Facebook company page URL. */
904
+ facebookUrl?: string;
905
+ /** @description The company's display name. */
906
+ name: string;
907
+ /** @description URL-friendly slug for the company. Auto-generated from `name` when omitted. */
908
+ slug?: string;
909
+ };
910
+ CreateEducationBody: {
911
+ institutionName: string;
912
+ institutionUrl?: string;
913
+ degree?: string;
914
+ fieldOfStudy?: string;
915
+ grade?: string;
916
+ activitiesAndSocieties?: string;
917
+ startDate?: string;
918
+ endDate?: string;
919
+ description?: string;
920
+ sortOrder?: number;
921
+ };
922
+ CreateExperienceBody: {
923
+ title: string;
924
+ companyName: string;
925
+ startDate: string;
926
+ companyUrl?: string;
927
+ location?: string;
928
+ employmentType?: string;
929
+ locationType?: string;
930
+ foundVia?: string;
931
+ endDate?: string;
932
+ description?: string;
933
+ sortOrder?: number;
934
+ };
935
+ CreateJobBody: {
936
+ /** @description The ID of an existing company. Provide either `companyId` or `company`, not both. */
937
+ companyId?: string;
938
+ /** @description Long-form description of the role. Up to 25,000 characters. */
939
+ description: string;
940
+ /** @description URL-friendly slug for the job. Auto-generated from `title` when omitted. */
941
+ slug?: string;
942
+ /**
943
+ * @description Employment type of the role.
944
+ * @enum {string}
945
+ */
946
+ employmentType?: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other";
947
+ /**
948
+ * @description Whether the role is on-site, hybrid, or fully remote.
949
+ * @enum {string}
950
+ */
951
+ remoteOption?: "on_site" | "hybrid" | "remote";
952
+ /** @description Where remote candidates must hold work authorization. Each entry is the smallest relevant scope: `worldwide`, a `world_region` (EMEA / LATAM / NA / APAC), a `continent`, a `region`, a `subregion`, a `custom` group (e.g. `EU`), a `country` (ISO 3166-1 alpha-2), or a `subdivision` (ISO 3166-2). Subdivisions auto-imply their parent country in the derived `remoteWorkPermitCountryCodes` output. Worldwide is mutually exclusive with all other entries. The canonical `{type, value}` set is published at `GET /v1/taxonomies/remote-permits`. Pass `[]` to clear an existing constraint. */
953
+ remotePermits?: {
954
+ /** @enum {string} */
955
+ type: "worldwide" | "world_region" | "continent" | "region" | "subregion" | "subdivision" | "country" | "custom";
956
+ value: string;
957
+ }[];
958
+ /** @description Where remote candidates must be timezone-compatible. Each entry mirrors the `remotePermits` shape (`world_region`, `continent`, `region`, `subregion`, `country`) plus `timezone` (specific IANA name with optional `plusMinus` ±N hours expansion) and `all` (every timezone — equivalent of `worldwide` for permits). The canonical `{type, value}` set is published at `GET /v1/taxonomies/remote-timezones`. **When omitted on POST**, the server auto-derives this from `remotePermits` (or `[{all,all}]` if neither was provided). **PATCH never auto-re-derives** — once set, only an explicit replacement updates the stored value, even when `remotePermits` changes. Pass `[]` to clear an existing constraint. */
959
+ remoteTimezones?: {
960
+ /** @enum {string} */
961
+ type: "all" | "world_region" | "continent" | "region" | "subregion" | "country" | "timezone";
962
+ value: string;
963
+ plusMinus?: number;
964
+ }[];
965
+ /**
966
+ * @description Whether the employer sponsors visas for remote candidates. One of `yes`, `no`, or `unknown`.
967
+ * @enum {string}
968
+ */
969
+ remoteSponsorship?: "yes" | "no" | "unknown";
970
+ /**
971
+ * @description Seniority level of the role.
972
+ * @enum {string}
973
+ */
974
+ seniority?: "entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive";
975
+ /** @description Where candidates apply. Accepts an HTTPS URL, a `mailto:` URI, or a bare email address (which is normalized to `mailto:` form). */
976
+ applicationUrl: string;
977
+ /** @description Minimum salary, in `salaryCurrency` units. */
978
+ salaryMin?: number;
979
+ /** @description Maximum salary, in `salaryCurrency` units. */
980
+ salaryMax?: number;
981
+ /** @description Three-letter ISO 4217 currency code for `salaryMin` and `salaryMax`. */
982
+ salaryCurrency?: string;
983
+ /**
984
+ * @description Period the `salaryMin` and `salaryMax` figures are quoted against.
985
+ * @enum {string}
986
+ */
987
+ salaryTimeframe?: "per_year" | "per_month" | "per_week" | "per_day" | "per_hour";
988
+ /** @description Whether the job appears in featured slots on the public board. */
989
+ isFeatured?: boolean;
990
+ /** @description Job expiry as a Unix epoch in milliseconds. On create, omitted or `null` defaults to 30 days from creation. On PATCH, pass `null` to clear an existing expiry. Past timestamps remove the job from the public board. */
991
+ expiresAt?: number | unknown | unknown;
992
+ /** @description Time at which the job was first published, as a Unix epoch in milliseconds. When omitted on create with `status: "published"`, the server stamps the current time. Useful for bulk-importing historical jobs while preserving original publication dates. PATCH may overwrite an existing value but cannot clear it. */
993
+ publishedAt?: number;
994
+ /** @description Required education credentials. Each value is one of `high_school`, `associate_degree`, `bachelor_degree`, `professional_certificate`, `postgraduate_degree`, or `no_requirements`. */
995
+ educationRequirements?: ("high_school" | "associate_degree" | "bachelor_degree" | "professional_certificate" | "postgraduate_degree" | "no_requirements")[];
996
+ /** @description Minimum required experience, expressed in months. */
997
+ experienceMonths?: number;
998
+ /** @description If `true`, equivalent experience may substitute for the listed education requirements. */
999
+ experienceInPlaceOfEducation?: boolean;
1000
+ /**
1001
+ * @description Period denominator for `inOfficeFrequency`.
1002
+ * @enum {string}
1003
+ */
1004
+ inOfficePeriod?: "per_week" | "per_month" | "per_year";
1005
+ /** @description How often the candidate must be in-office over `inOfficePeriod`. */
1006
+ inOfficeFrequency?: number;
1007
+ /** @description Physical office locations associated with the job. Each entry is forward-geocoded server-side; a country mismatch returns `400 jobs_unresolvable_location`. */
1008
+ officeLocations?: components["schemas"]["JobOfficeLocationInput"][];
1009
+ /** @description An external identifier for the job from your own system, such as an ATS requisition ID. Use this value to look up the job later via `GET /v1/jobs?externalId=...` for deduplication. Scoped per-account: two different accounts may reuse the same `externalId` without collision. Up to 255 characters. */
1010
+ externalId?: string;
1011
+ /** @description Board-defined custom-field values, keyed by the field `key` (definitions, including type and option keys, are published at `GET /v1/settings/job-form`). Writes are **additive**: on `PATCH` a key you send is set/overwritten and a key you omit is preserved (unsent keys are never cleared); on `POST` this initializes the bag. Send a key with an intentional-empty value — `null`, `""`, or `[]` — to **clear** it (`""`/`null` clear any type; `[]` clears a `multi_select`); `false` and `0` are kept as real values. Values must match the field type and `single_select`/`multi_select` must use defined option **keys** (not labels); a wrong-typed value is rejected (`custom_field_wrong_type`), never silently cleared. Unknown keys are ignored. The stored bag never contains `null`/empty values. */
1012
+ customFieldValues?: {
1013
+ [key: string]: string | string[] | boolean | number | unknown | unknown;
1014
+ };
1015
+ /** @description The job title. */
1016
+ title: string;
1017
+ company?: components["schemas"]["InlineCompanyInput"];
1018
+ /**
1019
+ * @description Initial status of the job. Defaults to `draft`. Only `draft` and `published` are writable here. The system-set values `expired` and `archived` are not — use the dedicated transitions (`POST /v1/jobs/:id/publish`, `/pause`, `/expire`) for status changes after create.
1020
+ * @enum {string}
1021
+ */
1022
+ status?: "draft" | "published";
1023
+ };
1024
+ CreateJobPostingBody: {
1025
+ submission: {
1026
+ companyName: string;
1027
+ companyWebsite?: string;
1028
+ contactName: string;
1029
+ contactEmail: string;
1030
+ title: string;
1031
+ description: string;
1032
+ employmentType: string;
1033
+ remoteOption: string;
1034
+ officeLocations: {
1035
+ /** @enum {string} */
1036
+ provider?: "mapbox";
1037
+ providerPlaceId?: string;
1038
+ displayName: string;
1039
+ countryCode?: string;
1040
+ region?: string;
1041
+ locality?: string;
1042
+ city?: string;
1043
+ latitude?: number;
1044
+ longitude?: number;
1045
+ boundingBox?: number[];
1046
+ raw?: {
1047
+ suggestion?: {
1048
+ [key: string]: unknown;
1049
+ };
1050
+ retrieve?: {
1051
+ [key: string]: unknown;
1052
+ };
1053
+ };
1054
+ }[];
1055
+ inOfficePeriod?: string;
1056
+ inOfficeFrequency?: number;
1057
+ seniority?: string;
1058
+ applicationUrl: string;
1059
+ salaryRangeEnabled: boolean;
1060
+ salaryMin?: number;
1061
+ salaryMax?: number;
1062
+ salaryTimeframe?: string;
1063
+ salaryCurrency?: string;
1064
+ selectedPlan?: string;
1065
+ isFeatured?: boolean;
1066
+ remoteWorkingPermits?: {
1067
+ type: string;
1068
+ value: string;
1069
+ label: string;
1070
+ }[];
1071
+ remoteTimezones?: {
1072
+ type: string;
1073
+ value: string;
1074
+ label: string;
1075
+ plusMinus: number;
1076
+ offset?: number;
1077
+ }[];
1078
+ /** @enum {string} */
1079
+ remoteSponsorship?: "yes" | "no" | "unknown";
1080
+ customFieldValues?: {
1081
+ [key: string]: string | string[] | boolean | number;
1082
+ };
1083
+ };
1084
+ remoteAllowedTzOffsets?: number[];
1085
+ remoteWorkPermitCountryCodes?: string[];
1086
+ logoUrl?: string;
1087
+ selectedBilling?: {
1088
+ type: string;
1089
+ id?: string;
1090
+ planId: string;
1091
+ };
1092
+ invoiceBilling?: {
1093
+ billingName?: string;
1094
+ address: {
1095
+ line1?: string;
1096
+ city?: string;
1097
+ postalCode?: string;
1098
+ country?: string;
1099
+ };
1100
+ taxId?: string;
1101
+ detailFields?: {
1102
+ name: string;
1103
+ value: string;
1104
+ }[];
1105
+ };
1106
+ colorMode?: string;
1107
+ };
1108
+ CreatePipelineStageBody: {
1109
+ /** @description The job whose pipeline gains the stage. */
1110
+ jobId: string;
1111
+ /** @description The stage label. */
1112
+ label: string;
1113
+ };
1114
+ CreateTagBody: {
1115
+ /** @description URL-friendly slug for the tag. Auto-generated from `name` when omitted. */
1116
+ slug?: string;
1117
+ /** @description Description for the tag. Sanitized HTML. */
1118
+ description?: string;
1119
+ /**
1120
+ * @description Tag visibility. One of `public` or `internal`.
1121
+ * @enum {string}
1122
+ */
1123
+ visibility?: "public" | "internal";
1124
+ /** @description SEO meta title for the tag page. */
1125
+ metaTitle?: string;
1126
+ /** @description SEO meta description for the tag page. */
1127
+ metaDescription?: string;
1128
+ /** @description The display name of the tag. */
1129
+ name: string;
1130
+ };
1131
+ CustomFieldDefinition: {
1132
+ /** @description Immutable per-board slug. The key in a job’s `customFieldValues`, and the frontend translation token (`customField.<key>.*`). */
1133
+ key: string;
1134
+ /** @description Authoring-default label; the localized public string lives in the board template. */
1135
+ label: string;
1136
+ /**
1137
+ * @description Field type, which dictates the value: `short_text`/`long_text` → string; `single_select` → one option key; `multi_select` → array of option keys; `boolean` → boolean; `number` → number.
1138
+ * @enum {string}
1139
+ */
1140
+ type: "short_text" | "long_text" | "single_select" | "multi_select" | "boolean" | "number";
1141
+ /** @description Present only for `single_select`/`multi_select`. A stored value is one (or, for multi, several) of these option `key`s — never a label. */
1142
+ options?: components["schemas"]["CustomFieldOption"][];
1143
+ /** @description When true, the value cannot be cleared or left empty on a write (rejected with `custom_field_required`). */
1144
+ required: boolean;
1145
+ /** @description Inclusive minimum for `number` fields, when set. */
1146
+ min?: number;
1147
+ /** @description Inclusive maximum for `number` fields, when set. */
1148
+ max?: number;
1149
+ };
1150
+ CustomFieldOption: {
1151
+ /** @description Stable option key — the value stored on a job, not the label. */
1152
+ key: string;
1153
+ /** @description Display label (authoring default; localized per board in the template). */
1154
+ label: string;
1155
+ };
1156
+ DuplicateJobBody: Record<string, never>;
1157
+ DynamicClientRegistrationRequest: {
1158
+ /** @description Array of redirect URIs the client may use. Must be HTTPS, except for `http://localhost` URIs in development. At least one entry is required. */
1159
+ redirect_uris: string[];
1160
+ /** @description Human-readable client name shown to users on the consent screen. Recommended for MCP clients; defaults to "MCP client" when omitted. */
1161
+ client_name?: string;
1162
+ /** @description Space-separated list of scopes the client may request. When omitted, the client is registered for all scopes. */
1163
+ scope?: string;
1164
+ /**
1165
+ * @description OAuth token endpoint authentication method. Use `none` for public PKCE clients that cannot keep a client secret.
1166
+ * @enum {string}
1167
+ */
1168
+ token_endpoint_auth_method?: "client_secret_basic" | "none";
1169
+ };
1170
+ DynamicClientRegistrationResponse: {
1171
+ /** @description Public OAuth client identifier. */
1172
+ client_id: string;
1173
+ /** @description Time at which the client was registered. Unix epoch in seconds. */
1174
+ client_id_issued_at: number;
1175
+ /** @description Plaintext OAuth client secret. Returned exactly once for confidential clients; omitted for public clients. */
1176
+ client_secret?: string;
1177
+ /** @description Time at which the client secret expires. Unix epoch in seconds, or `0` if the secret does not expire. Omitted for public clients. */
1178
+ client_secret_expires_at?: number;
1179
+ /** @description Array of redirect URIs registered for the client. */
1180
+ redirect_uris: string[];
1181
+ /** @description Human-readable client name shown to users on the consent screen. */
1182
+ client_name: string;
1183
+ /** @description OAuth grant types the client is permitted to use. */
1184
+ grant_types: string[];
1185
+ /** @description OAuth response types the client is permitted to use. */
1186
+ response_types: string[];
1187
+ /** @description Authentication method the client uses at the token endpoint. */
1188
+ token_endpoint_auth_method: string;
1189
+ /** @description Space-separated list of scopes the client may request. */
1190
+ scope: string;
1191
+ };
1192
+ EditMessageBody: {
1193
+ body: string;
1194
+ };
1195
+ EmployerApplicant: {
1196
+ id: string;
1197
+ /** @enum {string} */
1198
+ object: "employer_applicant";
1199
+ jobId: string;
1200
+ candidateBoardUserId: string | null;
1201
+ candidateProfileId: string | null;
1202
+ candidateProfileHandle: string | null;
1203
+ candidateName: string | null;
1204
+ candidateEmail: string | null;
1205
+ candidateHeadline: string | null;
1206
+ candidateLocation: string | null;
1207
+ coverNote: string | null;
1208
+ resumeFilename: string | null;
1209
+ /** @description A short-lived signed URL to the uploaded resume, or `null`. */
1210
+ resumeUrl: string | null;
1211
+ stage: string;
1212
+ /** @description How the application arrived (e.g. `native_apply`). */
1213
+ source: string;
1214
+ /** Format: date-time */
1215
+ appliedAt: string;
1216
+ timeline: components["schemas"]["EmployerApplicantTimelineEntry"][];
1217
+ };
1218
+ EmployerApplicantTimelineEntry: {
1219
+ id: string;
1220
+ /** @description The activity kind (e.g. `stage_changed`, `note_created`, `application_created`). */
1221
+ type: string;
1222
+ actorBoardUserId: string | null;
1223
+ actorName: string | null;
1224
+ noteId: string | null;
1225
+ /** @description The note text for a `note_created` entry, else `null`. */
1226
+ noteBody: string | null;
1227
+ fromStage: string | null;
1228
+ toStage: string | null;
1229
+ /** Format: date-time */
1230
+ createdAt: string;
1231
+ };
1232
+ EmployerBillingOption: {
1233
+ id: string;
1234
+ /** @enum {string} */
1235
+ object: "employer_billing_option";
1236
+ /** @enum {string} */
1237
+ type: "subscription" | "order";
1238
+ planId: string;
1239
+ planName: string;
1240
+ /** @enum {string} */
1241
+ planKind: "subscription" | "one_time" | "bundle";
1242
+ jobsRemaining: number;
1243
+ jobsTotal: number;
1244
+ featuredRemaining: number;
1245
+ featuredTotal: number;
1246
+ /**
1247
+ * Format: date-time
1248
+ * @description When a subscription renews, or `null` for one-time orders.
1249
+ */
1250
+ renewsAt: string | null;
1251
+ };
1252
+ EmployerCheckout: {
1253
+ /** @enum {string} */
1254
+ object: "employer_checkout";
1255
+ /** @enum {string} */
1256
+ status: "checkout" | "published" | "invoice_sent";
1257
+ /** @description The Stripe Checkout / hosted-invoice URL, or `null`. */
1258
+ checkoutUrl: string | null;
1259
+ jobId: string;
1260
+ jobSlug: string | null;
1261
+ };
1262
+ EmployerCheckoutBody: {
1263
+ billing: {
1264
+ /** @enum {string} */
1265
+ type: "new";
1266
+ planId: string;
1267
+ } | {
1268
+ /** @enum {string} */
1269
+ type: "order";
1270
+ planId: string;
1271
+ id: string;
1272
+ } | {
1273
+ /** @enum {string} */
1274
+ type: "subscription";
1275
+ planId: string;
1276
+ id: string;
1277
+ };
1278
+ invoiceBilling?: {
1279
+ billingName?: string;
1280
+ /** Format: email */
1281
+ email?: string;
1282
+ address?: {
1283
+ line1?: string;
1284
+ city?: string;
1285
+ postalCode?: string;
1286
+ country?: string;
1287
+ };
1288
+ taxId?: string;
1289
+ detailFields?: {
1290
+ name: string;
1291
+ value: string;
1292
+ }[];
1293
+ };
1294
+ isFeatured?: boolean;
1295
+ /**
1296
+ * Format: uri
1297
+ * @description Where Stripe returns the buyer on success. Defaults to the board's canonical employer pages.
1298
+ */
1299
+ successUrl?: string;
1300
+ /**
1301
+ * Format: uri
1302
+ * @description Where Stripe returns the buyer on cancel.
1303
+ */
1304
+ cancelUrl?: string;
1305
+ };
1306
+ EmployerCompany: {
1307
+ id: string;
1308
+ /** @enum {string} */
1309
+ object: "employer_company";
1310
+ name: string;
1311
+ slug: string;
1312
+ website: string | null;
1313
+ description: string | null;
1314
+ summary: string | null;
1315
+ xUrl: string | null;
1316
+ linkedinUrl: string | null;
1317
+ facebookUrl: string | null;
1318
+ logoUrl: string | null;
1319
+ };
1320
+ EmployerCreateJobBody: {
1321
+ /** @description Long-form description of the role. Up to 25,000 characters. */
1322
+ description: string;
1323
+ /** @description URL-friendly slug for the job. Auto-generated from `title` when omitted. */
1324
+ slug?: string;
1325
+ /**
1326
+ * @description Employment type of the role.
1327
+ * @enum {string}
1328
+ */
1329
+ employmentType?: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other";
1330
+ /**
1331
+ * @description Whether the role is on-site, hybrid, or fully remote.
1332
+ * @enum {string}
1333
+ */
1334
+ remoteOption?: "on_site" | "hybrid" | "remote";
1335
+ /** @description Where remote candidates must hold work authorization. Each entry is the smallest relevant scope: `worldwide`, a `world_region` (EMEA / LATAM / NA / APAC), a `continent`, a `region`, a `subregion`, a `custom` group (e.g. `EU`), a `country` (ISO 3166-1 alpha-2), or a `subdivision` (ISO 3166-2). Subdivisions auto-imply their parent country in the derived `remoteWorkPermitCountryCodes` output. Worldwide is mutually exclusive with all other entries. The canonical `{type, value}` set is published at `GET /v1/taxonomies/remote-permits`. Pass `[]` to clear an existing constraint. */
1336
+ remotePermits?: {
1337
+ /** @enum {string} */
1338
+ type: "worldwide" | "world_region" | "continent" | "region" | "subregion" | "subdivision" | "country" | "custom";
1339
+ value: string;
1340
+ }[];
1341
+ /** @description Where remote candidates must be timezone-compatible. Each entry mirrors the `remotePermits` shape (`world_region`, `continent`, `region`, `subregion`, `country`) plus `timezone` (specific IANA name with optional `plusMinus` ±N hours expansion) and `all` (every timezone — equivalent of `worldwide` for permits). The canonical `{type, value}` set is published at `GET /v1/taxonomies/remote-timezones`. **When omitted on POST**, the server auto-derives this from `remotePermits` (or `[{all,all}]` if neither was provided). **PATCH never auto-re-derives** — once set, only an explicit replacement updates the stored value, even when `remotePermits` changes. Pass `[]` to clear an existing constraint. */
1342
+ remoteTimezones?: {
1343
+ /** @enum {string} */
1344
+ type: "all" | "world_region" | "continent" | "region" | "subregion" | "country" | "timezone";
1345
+ value: string;
1346
+ plusMinus?: number;
1347
+ }[];
1348
+ /**
1349
+ * @description Whether the employer sponsors visas for remote candidates. One of `yes`, `no`, or `unknown`.
1350
+ * @enum {string}
1351
+ */
1352
+ remoteSponsorship?: "yes" | "no" | "unknown";
1353
+ /**
1354
+ * @description Seniority level of the role.
1355
+ * @enum {string}
1356
+ */
1357
+ seniority?: "entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive";
1358
+ /** @description Where candidates apply. Accepts an HTTPS URL, a `mailto:` URI, or a bare email address (normalized to `mailto:` form). */
1359
+ applicationUrl: string;
1360
+ /** @description Minimum salary, in `salaryCurrency` units. */
1361
+ salaryMin?: number;
1362
+ /** @description Maximum salary, in `salaryCurrency` units. */
1363
+ salaryMax?: number;
1364
+ /** @description Three-letter ISO 4217 currency code for `salaryMin` and `salaryMax`. */
1365
+ salaryCurrency?: string;
1366
+ /**
1367
+ * @description Period the `salaryMin` and `salaryMax` figures are quoted against.
1368
+ * @enum {string}
1369
+ */
1370
+ salaryTimeframe?: "per_year" | "per_month" | "per_week" | "per_day" | "per_hour";
1371
+ /** @description Required education credentials. Each value is one of `high_school`, `associate_degree`, `bachelor_degree`, `professional_certificate`, `postgraduate_degree`, or `no_requirements`. */
1372
+ educationRequirements?: ("high_school" | "associate_degree" | "bachelor_degree" | "professional_certificate" | "postgraduate_degree" | "no_requirements")[];
1373
+ /** @description Minimum required experience, expressed in months. */
1374
+ experienceMonths?: number;
1375
+ /** @description If `true`, equivalent experience may substitute for the listed education requirements. */
1376
+ experienceInPlaceOfEducation?: boolean;
1377
+ /**
1378
+ * @description Period denominator for `inOfficeFrequency`.
1379
+ * @enum {string}
1380
+ */
1381
+ inOfficePeriod?: "per_week" | "per_month" | "per_year";
1382
+ /** @description How often the candidate must be in-office over `inOfficePeriod`. */
1383
+ inOfficeFrequency?: number;
1384
+ /** @description Physical office locations associated with the job. Each entry is forward-geocoded server-side; a country mismatch returns `400 jobs_unresolvable_location`. */
1385
+ officeLocations?: components["schemas"]["JobOfficeLocationInput"][];
1386
+ /** @description The job title. */
1387
+ title: string;
1388
+ };
1389
+ EmployerJob: components["schemas"]["EmployerJobSummary"] & {
1390
+ /** @description Long-form description of the role, or `null` if not specified. */
1391
+ description: string | null;
1392
+ /** @description Where candidates apply, or `null` if not specified. An HTTPS URL or `mailto:` URI. */
1393
+ applicationUrl: string | null;
1394
+ /** @description Hierarchical permit selection authored by the employer. The three `remoteWorkPermit*` and `remoteWorldwide` fields are read-only derived projections. */
1395
+ remotePermits: {
1396
+ type: string;
1397
+ value: string;
1398
+ }[];
1399
+ /** @description Read-only — derived from `remotePermits`. */
1400
+ remoteWorldwide: boolean | null;
1401
+ /** @description Hierarchical timezone selection. The flat `remoteAllowedTzOffsets` below is the read-only derived projection. */
1402
+ remoteTimezones: {
1403
+ type: string;
1404
+ value: string;
1405
+ plusMinus?: number;
1406
+ }[];
1407
+ /** @description Read-only — derived from `remoteTimezones`. UTC hour offsets. */
1408
+ remoteAllowedTzOffsets: number[];
1409
+ /** @description Read-only — derived from `remotePermits`. ISO 3166-1 alpha-2. */
1410
+ remoteWorkPermitCountryCodes: string[];
1411
+ /** @description Read-only — derived from `remotePermits`. ISO 3166-2. */
1412
+ remoteWorkPermitSubdivisionCodes: string[];
1413
+ /**
1414
+ * @description Whether the employer sponsors visas for remote candidates. One of `yes`, `no`, or `unknown`.
1415
+ * @enum {string}
1416
+ */
1417
+ remoteSponsorship: "yes" | "no" | "unknown";
1418
+ /** @description Required education credentials. */
1419
+ educationRequirements: ("high_school" | "associate_degree" | "bachelor_degree" | "professional_certificate" | "postgraduate_degree" | "no_requirements")[];
1420
+ /** @description Minimum required experience in months, or `null`. */
1421
+ experienceMonths: number | null;
1422
+ /** @description If `true`, equivalent experience may substitute for education. `null` if not specified. */
1423
+ experienceInPlaceOfEducation: boolean | null;
1424
+ /**
1425
+ * @description Period denominator for `inOfficeFrequency`, or `null`.
1426
+ * @enum {string|null}
1427
+ */
1428
+ inOfficePeriod: "per_week" | "per_month" | "per_year" | null;
1429
+ /** @description How often the candidate must be in-office, or `null`. */
1430
+ inOfficeFrequency: number | null;
1431
+ company: components["schemas"]["JobCompany"];
1432
+ /** @description Physical office locations associated with the job. */
1433
+ officeLocations: components["schemas"]["JobOfficeLocation"][];
1434
+ };
1435
+ /** @description Public-only links. The operator dashboard URL is intentionally omitted on employer responses. */
1436
+ EmployerJobLinks: {
1437
+ /**
1438
+ * Format: uri
1439
+ * @description Canonical public URL for this job, or `null` when the job has no slug or no associated company slug (so a stable URL cannot be assembled). A draft carries a URL but only resolves once published.
1440
+ */
1441
+ public: string | null;
1442
+ };
1443
+ EmployerJobSummary: {
1444
+ /** @description Unique identifier for the object. Use this value as the `{id}` path parameter for the job endpoints (e.g. `GET /v1/jobs/{id}`). */
1445
+ id: string;
1446
+ /**
1447
+ * @description String representing the object's type. Objects of the same type share the same value.
1448
+ * @enum {string}
1449
+ */
1450
+ object: "employer_job";
1451
+ /** @description The job title. */
1452
+ title: string;
1453
+ /** @description URL-friendly slug used in public board URLs, or `null` if no slug is set. */
1454
+ slug: string | null;
1455
+ /**
1456
+ * @description Current status of the job. One of `draft`, `published`, `expired`, or `archived`.
1457
+ * @enum {string}
1458
+ */
1459
+ status: "draft" | "published" | "expired" | "archived";
1460
+ /** @description Identifier of the company the job belongs to, or `null` if no company is attached. */
1461
+ companyId: string | null;
1462
+ /**
1463
+ * @description Employment type of the role, or `null` if not specified.
1464
+ * @enum {string|null}
1465
+ */
1466
+ employmentType: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other" | null;
1467
+ /**
1468
+ * @description Whether the role is on-site, hybrid, or fully remote, or `null` if not specified.
1469
+ * @enum {string|null}
1470
+ */
1471
+ remoteOption: "on_site" | "hybrid" | "remote" | null;
1472
+ /**
1473
+ * @description Seniority level of the role, or `null` if not specified.
1474
+ * @enum {string|null}
1475
+ */
1476
+ seniority: "entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive" | null;
1477
+ /** @description Minimum salary in `salaryCurrency` units, or `null` if not specified. */
1478
+ salaryMin: number | null;
1479
+ /** @description Maximum salary in `salaryCurrency` units, or `null` if not specified. */
1480
+ salaryMax: number | null;
1481
+ /** @description Three-letter ISO 4217 currency code for the salary range, or `null` if no salary is specified. */
1482
+ salaryCurrency: string | null;
1483
+ /**
1484
+ * @description Period the salary range is quoted against, or `null` if no salary is specified.
1485
+ * @enum {string|null}
1486
+ */
1487
+ salaryTimeframe: "per_year" | "per_month" | "per_week" | "per_day" | "per_hour" | null;
1488
+ /** @description Whether the job appears in featured slots on the public board. */
1489
+ isFeatured: boolean;
1490
+ /** @description Time at which the job was first published, or `null` if not yet published. ISO 8601 datetime. */
1491
+ publishedAt: string | null;
1492
+ /** @description Time at which the job expires, or `null` if no expiry is set. ISO 8601 datetime. */
1493
+ expiresAt: string | null;
1494
+ /** @description Time at which the job was created. ISO 8601 datetime. */
1495
+ createdAt: string;
1496
+ /** @description Time at which the job was last updated. ISO 8601 datetime. */
1497
+ updatedAt: string;
1498
+ links: components["schemas"]["EmployerJobLinks"];
1499
+ };
1500
+ EmployerPipeline: {
1501
+ /** @enum {string} */
1502
+ object: "employer_pipeline";
1503
+ job: {
1504
+ id: string;
1505
+ title: string;
1506
+ status: string;
1507
+ /** Format: date-time */
1508
+ expiresAt: string | null;
1509
+ };
1510
+ stages: components["schemas"]["EmployerPipelineStage"][];
1511
+ applicants: components["schemas"]["EmployerApplicant"][];
1512
+ };
1513
+ EmployerPipelineStage: {
1514
+ id: string;
1515
+ /** @enum {string} */
1516
+ object: "employer_pipeline_stage";
1517
+ jobId: string;
1518
+ label: string;
1519
+ /** @description The stable system meaning (`review`/`offer`/`hired`/`rejected`), or `null` for a custom employer stage. */
1520
+ systemStage: string | null;
1521
+ isProtected: boolean;
1522
+ hidden: boolean;
1523
+ position: number;
1524
+ };
1525
+ EmployerUpdateJobBody: {
1526
+ /** @description Long-form description of the role. Up to 25,000 characters. */
1527
+ description?: string;
1528
+ /** @description URL-friendly slug for the job. Auto-generated from `title` when omitted. */
1529
+ slug?: string;
1530
+ /**
1531
+ * @description Employment type of the role.
1532
+ * @enum {string}
1533
+ */
1534
+ employmentType?: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other";
1535
+ /**
1536
+ * @description Whether the role is on-site, hybrid, or fully remote.
1537
+ * @enum {string}
1538
+ */
1539
+ remoteOption?: "on_site" | "hybrid" | "remote";
1540
+ /** @description Where remote candidates must hold work authorization. Each entry is the smallest relevant scope: `worldwide`, a `world_region` (EMEA / LATAM / NA / APAC), a `continent`, a `region`, a `subregion`, a `custom` group (e.g. `EU`), a `country` (ISO 3166-1 alpha-2), or a `subdivision` (ISO 3166-2). Subdivisions auto-imply their parent country in the derived `remoteWorkPermitCountryCodes` output. Worldwide is mutually exclusive with all other entries. The canonical `{type, value}` set is published at `GET /v1/taxonomies/remote-permits`. Pass `[]` to clear an existing constraint. */
1541
+ remotePermits?: {
1542
+ /** @enum {string} */
1543
+ type: "worldwide" | "world_region" | "continent" | "region" | "subregion" | "subdivision" | "country" | "custom";
1544
+ value: string;
1545
+ }[];
1546
+ /** @description Where remote candidates must be timezone-compatible. Each entry mirrors the `remotePermits` shape (`world_region`, `continent`, `region`, `subregion`, `country`) plus `timezone` (specific IANA name with optional `plusMinus` ±N hours expansion) and `all` (every timezone — equivalent of `worldwide` for permits). The canonical `{type, value}` set is published at `GET /v1/taxonomies/remote-timezones`. **When omitted on POST**, the server auto-derives this from `remotePermits` (or `[{all,all}]` if neither was provided). **PATCH never auto-re-derives** — once set, only an explicit replacement updates the stored value, even when `remotePermits` changes. Pass `[]` to clear an existing constraint. */
1547
+ remoteTimezones?: {
1548
+ /** @enum {string} */
1549
+ type: "all" | "world_region" | "continent" | "region" | "subregion" | "country" | "timezone";
1550
+ value: string;
1551
+ plusMinus?: number;
1552
+ }[];
1553
+ /**
1554
+ * @description Whether the employer sponsors visas for remote candidates. One of `yes`, `no`, or `unknown`.
1555
+ * @enum {string}
1556
+ */
1557
+ remoteSponsorship?: "yes" | "no" | "unknown";
1558
+ /**
1559
+ * @description Seniority level of the role.
1560
+ * @enum {string}
1561
+ */
1562
+ seniority?: "entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive";
1563
+ /** @description Where candidates apply. Accepts an HTTPS URL, a `mailto:` URI, or a bare email address (which is normalized to `mailto:` form). */
1564
+ applicationUrl?: string;
1565
+ /** @description Minimum salary, in `salaryCurrency` units. */
1566
+ salaryMin?: number;
1567
+ /** @description Maximum salary, in `salaryCurrency` units. */
1568
+ salaryMax?: number;
1569
+ /** @description Three-letter ISO 4217 currency code for `salaryMin` and `salaryMax`. */
1570
+ salaryCurrency?: string;
1571
+ /**
1572
+ * @description Period the `salaryMin` and `salaryMax` figures are quoted against.
1573
+ * @enum {string}
1574
+ */
1575
+ salaryTimeframe?: "per_year" | "per_month" | "per_week" | "per_day" | "per_hour";
1576
+ /** @description Required education credentials. Each value is one of `high_school`, `associate_degree`, `bachelor_degree`, `professional_certificate`, `postgraduate_degree`, or `no_requirements`. */
1577
+ educationRequirements?: ("high_school" | "associate_degree" | "bachelor_degree" | "professional_certificate" | "postgraduate_degree" | "no_requirements")[];
1578
+ /** @description Minimum required experience, expressed in months. */
1579
+ experienceMonths?: number;
1580
+ /** @description If `true`, equivalent experience may substitute for the listed education requirements. */
1581
+ experienceInPlaceOfEducation?: boolean;
1582
+ /**
1583
+ * @description Period denominator for `inOfficeFrequency`.
1584
+ * @enum {string}
1585
+ */
1586
+ inOfficePeriod?: "per_week" | "per_month" | "per_year";
1587
+ /** @description How often the candidate must be in-office over `inOfficePeriod`. */
1588
+ inOfficeFrequency?: number;
1589
+ /** @description Physical office locations associated with the job. Each entry is forward-geocoded server-side; a country mismatch returns `400 jobs_unresolvable_location`. */
1590
+ officeLocations?: components["schemas"]["JobOfficeLocationInput"][];
1591
+ /** @description The job title. */
1592
+ title?: string;
1593
+ };
1594
+ FindOrCreateCompanyBody: {
1595
+ /** @description The company's display name. */
1596
+ name: string;
1597
+ /** @description Public company website URL. Used to resolve to an existing company by domain before falling back to creation. */
1598
+ website?: string;
1599
+ /** @description One-line summary of the company. Up to 280 characters. */
1600
+ summary?: string;
1601
+ /** @description If `true` (default), falls back to matching by `name` when no website match is found. Set to `false` to match by website domain only. */
1602
+ matchByName?: boolean;
1603
+ /** @description If `true` (default), creates a new company when no match is found. Set to `false` to receive a `404 companies_not_found` response instead. */
1604
+ createIfMissing?: boolean;
1605
+ };
1606
+ HandleAvailability: {
1607
+ /** @enum {string} */
1608
+ object: "handle_availability";
1609
+ handle: string;
1610
+ available: boolean;
1611
+ };
1612
+ /** @description An inline company payload, resolved via `find-or-create` before the job is created. Provide either `company` or `companyId`, not both. */
1613
+ InlineCompanyInput: {
1614
+ /** @description The company's display name. */
1615
+ name: string;
1616
+ /** @description Public company website URL. Used to resolve to an existing company by domain before falling back to creation. */
1617
+ website?: string;
1618
+ /** @description One-line summary of the company. Up to 280 characters. */
1619
+ summary?: string;
1620
+ /** @description If `true` (default), falls back to matching by `name` when no website match is found. Set to `false` to match by website domain only. */
1621
+ matchByName?: boolean;
1622
+ /** @description If `true` (default), creates a new company when no match is found. Set to `false` to receive a `404 companies_not_found` response instead. */
1623
+ createIfMissing?: boolean;
1624
+ };
1625
+ Job: components["schemas"]["JobSummary"] & {
1626
+ /** @description Public + admin URLs for this job. `public` may be `null` if the job lacks a slug or company-slug. */
1627
+ links?: components["schemas"]["ResourceLinks"] & {
1628
+ /**
1629
+ * Format: uri
1630
+ * @description Canonical public URL for this job, or `null` when the job has no slug or no associated company slug (so a stable URL cannot be assembled).
1631
+ */
1632
+ public?: string | null;
1633
+ };
1634
+ /** @description Long-form description of the role, or `null` if not specified. */
1635
+ description: string | null;
1636
+ /** @description Where candidates apply, or `null` if not specified. An HTTPS URL or `mailto:` URI. */
1637
+ applicationUrl: string | null;
1638
+ /** @description Hierarchical permit selection authored by the caller. Lossless round-trip with the input — `[{type:"world_region",value:"EMEA"}]` goes in and comes out the same. The three `remoteWorkPermit*` and `remoteWorldwide` fields below are read-only derived projections of this list. */
1639
+ remotePermits: {
1640
+ type: string;
1641
+ value: string;
1642
+ }[];
1643
+ /** @description Read-only — derived from `remotePermits`. `true` only when the authored selection is a single `{type:"worldwide"}` entry. */
1644
+ remoteWorldwide: boolean | null;
1645
+ /** @description Hierarchical timezone selection. Lossless round-trip with the authored input. When omitted on POST, the server auto-derives this from `remotePermits` (or `[{all,all}]` if neither was provided). PATCH never auto-re-derives — once set, only an explicit replacement updates the stored value. The flat `remoteAllowedTzOffsets` field below is the read-only derived projection used by search. */
1646
+ remoteTimezones: {
1647
+ type: string;
1648
+ value: string;
1649
+ plusMinus?: number;
1650
+ }[];
1651
+ /** @description Read-only — derived from `remoteTimezones` (per-country/per-region offset fan-out). UTC hour offsets used by the job-search index. */
1652
+ remoteAllowedTzOffsets: number[];
1653
+ /** @description Read-only — derived from `remotePermits` (hierarchical groups fan out to alpha2 sets; subdivisions auto-add the parent country). ISO 3166-1 alpha-2 codes. */
1654
+ remoteWorkPermitCountryCodes: string[];
1655
+ /** @description Read-only — derived from `remotePermits` (subdivision entries only). ISO 3166-2 codes. */
1656
+ remoteWorkPermitSubdivisionCodes: string[];
1657
+ /**
1658
+ * @description Whether the employer sponsors visas for remote candidates. One of `yes`, `no`, or `unknown`.
1659
+ * @enum {string}
1660
+ */
1661
+ remoteSponsorship: "yes" | "no" | "unknown";
1662
+ /** @description Required education credentials. Each value is one of `high_school`, `associate_degree`, `bachelor_degree`, `professional_certificate`, `postgraduate_degree`, or `no_requirements`. */
1663
+ educationRequirements: ("high_school" | "associate_degree" | "bachelor_degree" | "professional_certificate" | "postgraduate_degree" | "no_requirements")[];
1664
+ /** @description Minimum required experience in months, or `null` if not specified. */
1665
+ experienceMonths: number | null;
1666
+ /** @description If `true`, equivalent experience may substitute for the listed education requirements. `null` if not specified. */
1667
+ experienceInPlaceOfEducation: boolean | null;
1668
+ /**
1669
+ * @description Period denominator for `inOfficeFrequency`, or `null` if not specified.
1670
+ * @enum {string|null}
1671
+ */
1672
+ inOfficePeriod: "per_week" | "per_month" | "per_year" | null;
1673
+ /** @description How often the candidate must be in-office over `inOfficePeriod`, or `null` if not specified. */
1674
+ inOfficeFrequency: number | null;
1675
+ company: components["schemas"]["JobCompany"];
1676
+ /** @description Physical office locations associated with the job. */
1677
+ officeLocations: components["schemas"]["JobOfficeLocation"][];
1678
+ };
1679
+ /** @description Embedded company resource for the job, or `null` if no company is attached. */
1680
+ JobCompany: {
1681
+ /** @description Unique identifier for the company. */
1682
+ id: string;
1683
+ /** @description Display name of the company, or `null` if not yet set. */
1684
+ name: string | null;
1685
+ /** @description URL slug of the company, or `null` if not yet set. */
1686
+ slug: string | null;
1687
+ /** @description URL of the company logo, or `null` if no logo is set. */
1688
+ logoUrl: string | null;
1689
+ /** @description Company website URL, or `null` if no website is set. */
1690
+ website: string | null;
1691
+ } | null;
1692
+ JobFormConfig: {
1693
+ sponsorship?: {
1694
+ visible: boolean;
1695
+ };
1696
+ salary?: {
1697
+ visible: boolean;
1698
+ required?: boolean;
1699
+ minBound?: number;
1700
+ maxBound?: number;
1701
+ allowedCurrencies?: string[];
1702
+ };
1703
+ seniority?: {
1704
+ visible: boolean;
1705
+ required?: boolean;
1706
+ allowedOptions?: string[];
1707
+ };
1708
+ workArrangement?: {
1709
+ allowedOptions: string[];
1710
+ };
1711
+ employmentType?: {
1712
+ allowedOptions: string[];
1713
+ };
1714
+ location?: {
1715
+ visible: boolean;
1716
+ allowedCountries?: string[];
1717
+ };
1718
+ /** @description Board-defined custom field definitions, in display order. Read these to learn which `customFieldValues` keys, types, and option keys a job accepts on POST/PATCH /v1/jobs. */
1719
+ customFields?: components["schemas"]["CustomFieldDefinition"][];
1720
+ };
1721
+ JobOfficeLocation: {
1722
+ /** @description ISO 3166-1 alpha-2 country code, or `null` if the location was not resolved. */
1723
+ countryCode: string | null;
1724
+ /** @description Full country name, or `null` if the location was not resolved. */
1725
+ country: string | null;
1726
+ /** @description Neighborhood or sub-locality, or `null` if not resolved. */
1727
+ locality: string | null;
1728
+ /** @description City, or `null` if not resolved. */
1729
+ city: string | null;
1730
+ /** @description Region, state, or province name, or `null` if not resolved. */
1731
+ region: string | null;
1732
+ /** @description Region or state code (e.g. `CA` for California), or `null` if not resolved. */
1733
+ regionCode: string | null;
1734
+ /** @description Postal or ZIP code, or `null` if not resolved. */
1735
+ postalCode: string | null;
1736
+ /** @description Pre-formatted display name for the location, or `null` if not resolved. */
1737
+ displayName: string | null;
1738
+ };
1739
+ JobOfficeLocationInput: {
1740
+ /** @description Neighborhood or sub-locality. */
1741
+ locality?: string;
1742
+ /** @description City. */
1743
+ city: string;
1744
+ /** @description Region, state, or province. */
1745
+ region?: string;
1746
+ /** @description ISO 3166-1 alpha-2 country code OR recognized country name/alias. Aliases are normalized to canonical alpha-2 server-side (e.g. `US`, `USA`, `United States` → `US`; `UK`, `GB`, `United Kingdom` → `GB`). */
1747
+ country: string;
1748
+ } | {
1749
+ /** @description Free-form location string (e.g. `"Berlin, Germany"`, `"Mountain View, California, USA"`). Mapbox parses + ranks candidates server-side; rejects on low confidence. */
1750
+ query: string;
1751
+ };
1752
+ JobPostingBillingCheck: {
1753
+ /** @enum {string} */
1754
+ object: "job_posting_billing_check";
1755
+ hasActiveBilling: boolean;
1756
+ };
1757
+ JobPostingBillingOptions: {
1758
+ /** @enum {string} */
1759
+ object: "job_posting_billing_options";
1760
+ options: {
1761
+ id: string;
1762
+ type: string;
1763
+ planId: string;
1764
+ planName: string;
1765
+ planKind: string;
1766
+ capacities: {
1767
+ key: string;
1768
+ total: number;
1769
+ used: number;
1770
+ remaining: number;
1771
+ }[];
1772
+ jobsRemaining: number;
1773
+ jobsTotal: number;
1774
+ featuredRemaining: number;
1775
+ featuredTotal: number;
1776
+ renewsAt: string | null;
1777
+ }[];
1778
+ };
1779
+ JobPostingBillingOptionsBody: {
1780
+ verificationToken: string;
1781
+ };
1782
+ JobPostingBillingVerification: {
1783
+ /** @enum {string} */
1784
+ object: "job_posting_billing_verification";
1785
+ success: boolean;
1786
+ };
1787
+ JobPostingCheckBillingBody: {
1788
+ /** Format: email */
1789
+ email: string;
1790
+ };
1791
+ JobPostingLogo: {
1792
+ /** @enum {string} */
1793
+ object: "job_posting_logo";
1794
+ publicUrl: string;
1795
+ };
1796
+ JobPostingPlan: {
1797
+ /** @enum {string} */
1798
+ object: "job_posting_plan";
1799
+ id: string;
1800
+ name: string;
1801
+ description: string | null;
1802
+ kind: string;
1803
+ /** @enum {string|null} */
1804
+ billingInterval: "month" | "year" | null;
1805
+ /** @enum {string|null} */
1806
+ purpose: "job_posting" | "talent_access" | null;
1807
+ isRecommended: boolean;
1808
+ displayOrder: number | null;
1809
+ invoiceOnly: boolean;
1810
+ /** @enum {string|null} */
1811
+ publishTiming: "on_issue" | "on_payment" | null;
1812
+ netTermsDays: number | null;
1813
+ prices: {
1814
+ currency: string;
1815
+ amountCents: number;
1816
+ isActive: boolean;
1817
+ }[];
1818
+ features: {
1819
+ key: string | null;
1820
+ value: string | null;
1821
+ }[];
1822
+ };
1823
+ JobPostingResult: {
1824
+ /** @enum {string} */
1825
+ object: "job_posting_result";
1826
+ /** @enum {string} */
1827
+ status: "checkout";
1828
+ checkoutUrl: string;
1829
+ jobId: string;
1830
+ } | {
1831
+ /** @enum {string} */
1832
+ object: "job_posting_result";
1833
+ /** @enum {string} */
1834
+ status: "published";
1835
+ jobId: string;
1836
+ jobSlug: string;
1837
+ } | {
1838
+ /** @enum {string} */
1839
+ object: "job_posting_result";
1840
+ /** @enum {string} */
1841
+ status: "pending_approval";
1842
+ jobId: string;
1843
+ } | {
1844
+ /** @enum {string} */
1845
+ object: "job_posting_result";
1846
+ /** @enum {string} */
1847
+ status: "invoice_sent";
1848
+ jobId: string;
1849
+ };
1850
+ JobPostingSendVerificationBody: {
1851
+ /** Format: email */
1852
+ email: string;
1853
+ };
1854
+ JobPostingSubscriptionEntitlements: {
1855
+ /** @enum {string} */
1856
+ object: "job_posting_subscription_entitlements";
1857
+ hasSubscription: boolean;
1858
+ subscriptionId: string | null;
1859
+ canFeature: boolean | null;
1860
+ featuredSlotsRemaining: number | null;
1861
+ featuredSlotsTotal: number | null;
1862
+ maxActiveRemaining: number | null;
1863
+ maxActiveTotal: number | null;
1864
+ featureSelectionMode: string | null;
1865
+ };
1866
+ JobPostingSubscriptionEntitlementsBody: {
1867
+ /** Format: email */
1868
+ email: string;
1869
+ planId: string;
1870
+ };
1871
+ JobSummary: {
1872
+ /** @description Unique identifier for the object. Use this value as the `{id}` path parameter for the job endpoints (e.g. `GET /v1/jobs/{id}`). */
1873
+ id: string;
1874
+ /**
1875
+ * @description String representing the object's type. Objects of the same type share the same value.
1876
+ * @enum {string}
1877
+ */
1878
+ object: "job";
1879
+ /** @description The job title. */
1880
+ title: string;
1881
+ /** @description URL-friendly slug used in public board URLs, or `null` if no slug is set. */
1882
+ slug: string | null;
1883
+ /**
1884
+ * @description Current status of the job. One of `draft`, `published`, `expired`, or `archived`.
1885
+ * @enum {string}
1886
+ */
1887
+ status: "draft" | "published" | "expired" | "archived";
1888
+ /** @description Identifier of the company the job belongs to, or `null` if no company is attached. */
1889
+ companyId: string | null;
1890
+ /**
1891
+ * @description Employment type of the role, or `null` if not specified.
1892
+ * @enum {string|null}
1893
+ */
1894
+ employmentType: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other" | null;
1895
+ /**
1896
+ * @description Whether the role is on-site, hybrid, or fully remote, or `null` if not specified.
1897
+ * @enum {string|null}
1898
+ */
1899
+ remoteOption: "on_site" | "hybrid" | "remote" | null;
1900
+ /**
1901
+ * @description Seniority level of the role, or `null` if not specified.
1902
+ * @enum {string|null}
1903
+ */
1904
+ seniority: "entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive" | null;
1905
+ /** @description Minimum salary in `salaryCurrency` units, or `null` if not specified. */
1906
+ salaryMin: number | null;
1907
+ /** @description Maximum salary in `salaryCurrency` units, or `null` if not specified. */
1908
+ salaryMax: number | null;
1909
+ /** @description Three-letter ISO 4217 currency code for the salary range, or `null` if no salary is specified. */
1910
+ salaryCurrency: string | null;
1911
+ /**
1912
+ * @description Period the salary range is quoted against, or `null` if no salary is specified.
1913
+ * @enum {string|null}
1914
+ */
1915
+ salaryTimeframe: "per_year" | "per_month" | "per_week" | "per_day" | "per_hour" | null;
1916
+ /** @description Whether the job appears in featured slots on the public board. */
1917
+ isFeatured: boolean;
1918
+ /** @description Time at which the job was first published, or `null` if not yet published. ISO 8601 datetime. */
1919
+ publishedAt: string | null;
1920
+ /** @description Time at which the job expires, or `null` if no expiry is set. ISO 8601 datetime. */
1921
+ expiresAt: string | null;
1922
+ /** @description Time at which the job was created. ISO 8601 datetime. */
1923
+ createdAt: string;
1924
+ /** @description Time at which the job was last updated. ISO 8601 datetime. */
1925
+ updatedAt: string;
1926
+ /** @description External identifier supplied by the caller on create, used for deduplication via `GET /v1/jobs?externalId=...`. `null` when no external identifier was set. */
1927
+ externalId: string | null;
1928
+ /** @description Board-defined custom-field values for this job, keyed by the field `key` (the definitions are published at `GET /v1/settings/job-form`). Each value is returned as stored: a string (`short_text` / `long_text` / a `single_select` option key), a string array (`multi_select` option keys), a boolean, or a number. Always an object — `{}` when the job has no custom-field values, never `null` or a missing field. Only real values are stored, so this never contains `null` or empty values. */
1929
+ customFieldValues: {
1930
+ [key: string]: string | string[] | boolean | number;
1931
+ };
1932
+ links: components["schemas"]["AdminOnlyResourceLinks"];
1933
+ };
1934
+ LegalPage: {
1935
+ /** @enum {string} */
1936
+ object: "legal_page";
1937
+ /** @description The resolved legal page type. */
1938
+ type: string;
1939
+ /** @description Page heading (H1), with `{{board_name}}` resolved. */
1940
+ title: string;
1941
+ /** @description Owner-authored prose as portable HTML (transitional field, ADR-0039 — the starter authors the layout). Empty string when the page has no text body. */
1942
+ content: string;
1943
+ /** @enum {string} */
1944
+ contentFormat: "html";
1945
+ /** @description Structured impressum legal-entity facts; `null` for non-impressum pages. */
1946
+ legalEntity: {
1947
+ legalName: string | null;
1948
+ address: string | null;
1949
+ } | null;
1950
+ };
1951
+ LocationSalaryDetail: {
1952
+ /** @enum {string} */
1953
+ object: "location_salary_detail";
1954
+ /** @description Immutable English source place slug — the salary-stats key. */
1955
+ sourceSlug: string;
1956
+ /** @description Board-language canonical URL slug — the starter 308 target. */
1957
+ canonicalSlug: string;
1958
+ placeName: string;
1959
+ placeId: string;
1960
+ adminLevel: string;
1961
+ countryCode: string;
1962
+ overallSalary: {
1963
+ avgMin: number;
1964
+ avgMax: number;
1965
+ medianMin: number;
1966
+ medianMax: number;
1967
+ p25Min: number;
1968
+ p75Max: number;
1969
+ jobCount: number;
1970
+ } | null;
1971
+ childLocations: {
1972
+ placeName: string;
1973
+ placeSlug: string;
1974
+ countryCode: string;
1975
+ avgSalaryMin: number;
1976
+ avgSalaryMax: number;
1977
+ medianSalaryMin: number;
1978
+ medianSalaryMax: number;
1979
+ p25SalaryMin: number;
1980
+ p75SalaryMax: number;
1981
+ jobCount: number;
1982
+ currency: string;
1983
+ }[];
1984
+ childLocationsByRegion: {
1985
+ regionName: string;
1986
+ regionSlug: string;
1987
+ cities: {
1988
+ placeName: string;
1989
+ placeSlug: string;
1990
+ countryCode: string;
1991
+ avgSalaryMin: number;
1992
+ avgSalaryMax: number;
1993
+ medianSalaryMin: number;
1994
+ medianSalaryMax: number;
1995
+ p25SalaryMin: number;
1996
+ p75SalaryMax: number;
1997
+ jobCount: number;
1998
+ currency: string;
1999
+ }[];
2000
+ }[];
2001
+ topCategories: {
2002
+ avgSalaryMin: number;
2003
+ avgSalaryMax: number;
2004
+ jobCount: number;
2005
+ categorySlug: string;
2006
+ categoryName: string;
2007
+ }[];
2008
+ topSkills: {
2009
+ avgSalaryMin: number;
2010
+ avgSalaryMax: number;
2011
+ jobCount: number;
2012
+ skillSlug: string;
2013
+ skillName: string;
2014
+ }[];
2015
+ siblingLocations: {
2016
+ placeName: string;
2017
+ placeSlug: string;
2018
+ countryCode: string;
2019
+ avgSalaryMin: number;
2020
+ avgSalaryMax: number;
2021
+ medianSalaryMin: number;
2022
+ medianSalaryMax: number;
2023
+ p25SalaryMin: number;
2024
+ p75SalaryMax: number;
2025
+ jobCount: number;
2026
+ currency: string;
2027
+ }[];
2028
+ boardOverallAvgMin: number | null;
2029
+ boardOverallAvgMax: number | null;
2030
+ currency: string;
2031
+ };
2032
+ LocationSkillsIndex: {
2033
+ /** @enum {string} */
2034
+ object: "location_skills_index";
2035
+ sourceSlug: string;
2036
+ canonicalSlug: string;
2037
+ placeName: string;
2038
+ skills: {
2039
+ slug: string;
2040
+ name: string;
2041
+ avgSalaryMin: number;
2042
+ avgSalaryMax: number;
2043
+ jobCount: number;
2044
+ }[];
2045
+ };
2046
+ LocationTitlesIndex: {
2047
+ /** @enum {string} */
2048
+ object: "location_titles_index";
2049
+ sourceSlug: string;
2050
+ canonicalSlug: string;
2051
+ placeName: string;
2052
+ titles: {
2053
+ slug: string;
2054
+ name: string;
2055
+ avgSalaryMin: number;
2056
+ avgSalaryMax: number;
2057
+ jobCount: number;
2058
+ }[];
2059
+ };
2060
+ MediaGet: components["schemas"]["MediaUpload"] & {
2061
+ /** @description Time at which the file was uploaded. ISO 8601 datetime. */
2062
+ uploadedAt: string;
2063
+ /** @description Resources currently referencing this file. Currently always `[]` — the resolver is not yet implemented. */
2064
+ referencedBy: {
2065
+ /** @description Type of the resource referencing this file. */
2066
+ resourceType: string;
2067
+ /** @description Identifier of the resource referencing this file. */
2068
+ resourceId: string;
2069
+ }[];
2070
+ };
2071
+ MediaUpload: {
2072
+ /** @description Unique identifier for the object. Use this value as the `{id}` path parameter for `GET /v1/media/{id}`. */
2073
+ id: string;
2074
+ /**
2075
+ * @description String representing the object's type. Objects of the same type share the same value.
2076
+ * @enum {string}
2077
+ */
2078
+ object: "media_upload";
2079
+ /** @description URL where the file can be downloaded. Permanent for files served from the assets domain; a signed URL for legacy files. Always set on the upload response; may be `null` on retrieval if the underlying blob has been deleted. */
2080
+ url: string | null;
2081
+ /** @description Time at which the signed `url` expires (ISO 8601 datetime), or `null` when the `url` is permanent and never expires. */
2082
+ urlExpiresAt: string | null;
2083
+ /** @description MIME type of the uploaded file. */
2084
+ mimeType: string;
2085
+ /** @description Size of the uploaded file, in bytes. */
2086
+ sizeBytes: number;
2087
+ /**
2088
+ * @description Resource type the file was uploaded for.
2089
+ * @enum {string}
2090
+ */
2091
+ purpose: "board_logo" | "board_hero" | "account_avatar" | "company_logo" | "blog_image";
2092
+ };
2093
+ Message: {
2094
+ id: string;
2095
+ /** @enum {string} */
2096
+ object: "message";
2097
+ conversationId: string;
2098
+ authorBoardUserId: string;
2099
+ recipientBoardUserId: string;
2100
+ body: string;
2101
+ author: components["schemas"]["MessageAuthor"];
2102
+ /** Format: date-time */
2103
+ sentAt: string;
2104
+ /** Format: date-time */
2105
+ editedAt: string | null;
2106
+ /** Format: date-time */
2107
+ deletedAt: string | null;
2108
+ /** Format: date-time */
2109
+ readAt: string | null;
2110
+ };
2111
+ MessageAuthor: {
2112
+ displayName: string;
2113
+ avatarUrl: string | null;
2114
+ companyName: string | null;
2115
+ };
2116
+ ModerationReport: {
2117
+ /** @enum {string} */
2118
+ object: "moderation_report";
2119
+ id: string;
2120
+ blocked: boolean;
2121
+ };
2122
+ MoveApplicantStageBody: {
2123
+ /** @description The target stage id. */
2124
+ stageId: string;
2125
+ };
2126
+ NotificationPreference: {
2127
+ /** @enum {string} */
2128
+ object: "notification_preference";
2129
+ /** @enum {string} */
2130
+ channel: "messageEmails" | "applicationEmails";
2131
+ subscribed: boolean;
2132
+ updatedAt: number | null;
2133
+ };
2134
+ /** @description Error envelope, populated once the operation reaches `failed`. `null` otherwise. */
2135
+ OperationErrorEnvelope: {
2136
+ /** @description Machine-readable error code. */
2137
+ code: string;
2138
+ /** @description Human-readable error message. */
2139
+ message: string;
2140
+ /** @description Additional structured details about the error, when present. */
2141
+ details?: unknown;
2142
+ /** @description Identifier of the request that produced the error. Use this to correlate with platform logs. */
2143
+ requestId?: string;
2144
+ } | null;
2145
+ /** @description Snapshot of the operation's progress, or `null` if the operation does not report progress. */
2146
+ OperationProgress: {
2147
+ /** @description Progress as a percentage between 0 and 100, when the operation reports a percentage. */
2148
+ percent?: number;
2149
+ /** @description Human-readable progress message, when available. */
2150
+ message?: string;
2151
+ /** @description Number of items processed so far, when applicable. */
2152
+ processed?: number;
2153
+ /** @description Total number of items to process, when known. */
2154
+ total?: number;
2155
+ } | null;
2156
+ OperationResource: {
2157
+ /** @description Unique identifier for the object. */
2158
+ id: string;
2159
+ /**
2160
+ * @description String representing the object's type. Objects of the same type share the same value.
2161
+ * @enum {string}
2162
+ */
2163
+ object: "operation";
2164
+ /** @description Operation kind, identifying which workflow the operation runs. */
2165
+ kind: string;
2166
+ /**
2167
+ * @description Current state of the operation.
2168
+ * @enum {string}
2169
+ */
2170
+ state: "pending" | "running" | "succeeded" | "failed" | "cancelled";
2171
+ /** @description Identifier of the account the operation belongs to. */
2172
+ accountId: string;
2173
+ progress: components["schemas"]["OperationProgress"];
2174
+ /** @description Operation result, populated once the operation reaches `succeeded`. Shape varies by `kind`. */
2175
+ result?: unknown;
2176
+ error: components["schemas"]["OperationErrorEnvelope"];
2177
+ /** @description Time at which the operation was created. ISO 8601 datetime. */
2178
+ createdAt: string;
2179
+ /** @description Time at which the operation was last updated. ISO 8601 datetime. */
2180
+ updatedAt: string;
2181
+ /** @description Time at which the operation reached a terminal state, or `null` if it has not yet completed. ISO 8601 datetime. */
2182
+ completedAt: string | null;
2183
+ /** @description Whether cancellation of the operation has been requested. */
2184
+ cancelRequested: boolean;
2185
+ /** @description Type of resource the operation acts on, or `null` for resource-less operations. */
2186
+ resourceType: string | null;
2187
+ /** @description Identifier of the resource the operation acts on, or `null` for resource-less operations. */
2188
+ resourceId: string | null;
2189
+ /** @description Identifier of the parent operation when this operation is a child of a fan-out, or `null` otherwise. */
2190
+ parentOperationId: string | null;
2191
+ };
2192
+ PatchSettingsBody: {
2193
+ /** @description Display name of the board. */
2194
+ name?: string;
2195
+ /** @description URL slug of the board. Lowercase alphanumeric and hyphens; reserved values (e.g. `admin`, `api`) are rejected. */
2196
+ slug?: string;
2197
+ /** @description Identifier of the custom domain to use as the primary public URL. */
2198
+ primaryDomainId?: string;
2199
+ /** @description Media storage ID returned by `POST /v1/media/upload` with `purpose=board_logo`. */
2200
+ logoStorageId?: string;
2201
+ /** @description Media storage ID returned by `POST /v1/media/upload` with `purpose=board_hero`. */
2202
+ heroStorageId?: string;
2203
+ /** @description Whether the board sits behind a password gate. Use `POST /v1/settings/password-protection` to set the actual password before enabling. */
2204
+ passwordProtectionEnabled?: boolean;
2205
+ /** @description Whether candidates can subscribe to email alerts for new jobs. */
2206
+ jobAlertsEnabled?: boolean;
2207
+ /** @description Whether candidate profiles are enabled on the board. */
2208
+ candidatesEnabled?: boolean;
2209
+ /** @description Whether employer self-serve flows are enabled. */
2210
+ employersEnabled?: boolean;
2211
+ /** @description Whether the public blog is exposed. */
2212
+ blogEnabled?: boolean;
2213
+ /** @description Whether the legal Impressum page is exposed (required in some jurisdictions). */
2214
+ impressumEnabled?: boolean;
2215
+ /** @description Whether jobs posted by employers from the free tier require admin approval before they appear on the public board. */
2216
+ requireApprovalFreeJobs?: boolean;
2217
+ /** @description Whether aggregated jobs (e.g. those scraped or imported from upstream sources) require admin approval before they appear on the public board. */
2218
+ requireApprovalAggregatedJobs?: boolean;
2219
+ /** @description Whether visitors must sign in to view jobs. */
2220
+ registrationWallEnabled?: boolean;
2221
+ /** @description Whether the public talent directory is enabled. */
2222
+ talentDirectoryEnabled?: boolean;
2223
+ /** @description Whether the Cavuno-branded footer is displayed on the public board. Plan-gated; lower-tier plans cannot disable this. */
2224
+ showCavunoBranding?: boolean;
2225
+ /** @description Default expiry, in days, applied to newly published jobs when no `expiresAt` is supplied. */
2226
+ defaultJobDurationDays?: number;
2227
+ /** @description Public contact email shown on the board. Pass `null` to clear. */
2228
+ contactEmail?: string | "" | unknown | unknown;
2229
+ /** @description Legal name of the entity operating the board. Pass `null` to clear. */
2230
+ companyLegalName?: string | "" | unknown | unknown;
2231
+ /** @description Postal address of the entity operating the board. Pass `null` to clear. */
2232
+ companyAddress?: string | "" | unknown | unknown;
2233
+ /** @description Public company website URL. Pass `null` to clear. */
2234
+ companyWebsiteUrl?: string | "" | unknown | unknown;
2235
+ /** @description Company X (Twitter) handle or profile URL. Pass `null` to clear. */
2236
+ companyXHandle?: string | "" | unknown | unknown;
2237
+ /** @description Company Facebook page URL. Pass `null` to clear. */
2238
+ companyFacebookUrl?: string | "" | unknown | unknown;
2239
+ /** @description Company LinkedIn page URL. Pass `null` to clear. */
2240
+ companyLinkedinUrl?: string | "" | unknown | unknown;
2241
+ /** @description Label shown for the talent directory in the public navigation. 1–50 characters. */
2242
+ talentNavLabel?: string;
2243
+ /** @description Custom copy displayed on the password gate. Up to 500 characters. Pass `null` to clear. */
2244
+ passwordProtectionMessage?: string | "" | unknown | unknown;
2245
+ /** @description Free-form configuration object merged into the existing config. Reserved keys (e.g. `passwordProtectionEnabled`, `adsenseClientId`, `jobAccessPaywallEnabled`) cannot be set here — use the dedicated endpoints instead. */
2246
+ config?: {
2247
+ [key: string]: unknown;
2248
+ };
2249
+ };
2250
+ PaywallOffer: {
2251
+ /** @enum {string} */
2252
+ object: "paywall_offer";
2253
+ /** @description The tier key posted to checkout (e.g. `monthly`, `lifetime`). */
2254
+ offerKey: string;
2255
+ label: string;
2256
+ billingLabel: string;
2257
+ amountCents: number;
2258
+ currency: string;
2259
+ /**
2260
+ * @description `recurring` tiers get a manage-subscription portal; `lifetime` do not.
2261
+ * @enum {string}
2262
+ */
2263
+ offerType: "recurring" | "lifetime";
2264
+ intervalUnit: string | null;
2265
+ intervalCount: number | null;
2266
+ isDefault: boolean;
2267
+ };
2268
+ Plan: {
2269
+ /** @enum {string} */
2270
+ object: "plan";
2271
+ id: string;
2272
+ name: string;
2273
+ description: string | null;
2274
+ /** @enum {string} */
2275
+ purpose: "job_posting" | "talent_access";
2276
+ /** @enum {string} */
2277
+ kind: "free" | "subscription" | "one_time" | "bundle";
2278
+ /** @enum {string|null} */
2279
+ billingInterval: "month" | "year" | null;
2280
+ isRecommended: boolean;
2281
+ displayOrder: number;
2282
+ invoiceOnly: boolean;
2283
+ /** @enum {string|null} */
2284
+ publishTiming: "on_issue" | "on_payment" | null;
2285
+ netTermsDays: number | null;
2286
+ price: {
2287
+ currency: string;
2288
+ amountCents: number;
2289
+ /** @description The public Stripe Price id used to start checkout. */
2290
+ stripePriceId: string | null;
2291
+ } | null;
2292
+ featureSummary: {
2293
+ durationDays: number;
2294
+ maxActiveJobs: number;
2295
+ featuredSlots: number;
2296
+ /** @enum {string} */
2297
+ featureSelectionMode: "auto" | "manual";
2298
+ };
2299
+ /** @description Talent-access allowances (per billing period). Present only when `purpose` is `talent_access`. `"unlimited"` is a sentinel value. */
2300
+ talent?: {
2301
+ unlocksPerPeriod: string;
2302
+ messagesPerPeriod: string;
2303
+ };
2304
+ };
2305
+ PublicBlogAdjacentPosts: {
2306
+ /** @enum {string} */
2307
+ object: "blog_adjacent_posts";
2308
+ previous: components["schemas"]["PublicBlogPostSummary"] | null;
2309
+ next: components["schemas"]["PublicBlogPostSummary"] | null;
2310
+ };
2311
+ PublicBlogAuthor: components["schemas"]["PublicBlogAuthorEmbed"] & {
2312
+ /** @enum {string} */
2313
+ object: "public_blog_author";
2314
+ };
2315
+ PublicBlogAuthorEmbed: {
2316
+ id: string;
2317
+ name: string;
2318
+ slug: string;
2319
+ bio: string | null;
2320
+ avatarUrl: string | null;
2321
+ websiteUrl: string | null;
2322
+ twitterUrl: string | null;
2323
+ linkedinUrl: string | null;
2324
+ githubUrl: string | null;
2325
+ };
2326
+ PublicBlogPost: components["schemas"]["PublicBlogPostSummary"] & {
2327
+ html: string | null;
2328
+ ogImageUrl: string | null;
2329
+ featureImageCaption: string | null;
2330
+ seoTitle: string | null;
2331
+ seoDescription: string | null;
2332
+ redirected: boolean;
2333
+ newSlug: string | null;
2334
+ };
2335
+ PublicBlogPostSummary: {
2336
+ id: string;
2337
+ /** @enum {string} */
2338
+ object: "public_blog_post";
2339
+ title: string;
2340
+ slug: string;
2341
+ featured: boolean;
2342
+ coverUrl: string | null;
2343
+ featureImageAlt: string | null;
2344
+ customExcerpt: string | null;
2345
+ readingTimeMin: number | null;
2346
+ publishedAt: string | null;
2347
+ canonicalUrl: string | null;
2348
+ createdAt: string;
2349
+ authors: components["schemas"]["PublicBlogAuthorEmbed"][];
2350
+ tags: components["schemas"]["PublicBlogTagEmbed"][];
2351
+ };
2352
+ PublicBlogSearchBody: {
2353
+ /** @description Free-text search query. Up to 200 characters. */
2354
+ query: string;
2355
+ /** @description An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results. */
2356
+ cursor?: string | null;
2357
+ /** @description A limit on the number of objects to be returned. Limit can range between 1 and 50. */
2358
+ limit?: number;
2359
+ };
2360
+ PublicBlogTag: components["schemas"]["PublicBlogTagEmbed"] & {
2361
+ /** @enum {string} */
2362
+ object: "public_blog_tag";
2363
+ };
2364
+ PublicBlogTagEmbed: {
2365
+ id: string;
2366
+ name: string;
2367
+ slug: string;
2368
+ description: string | null;
2369
+ };
2370
+ PublicBoardContext: {
2371
+ /** @enum {string} */
2372
+ object: "public_board";
2373
+ /** @description Immutable board identifier (`boards_…`). */
2374
+ id: string;
2375
+ /** @description Mutable canonical board slug. */
2376
+ slug: string;
2377
+ name: string;
2378
+ /** @description Board language (ISO code); defaults to "en". */
2379
+ language: string;
2380
+ logoUrl: string | null;
2381
+ /** @description Active custom-domain hostname, or null. */
2382
+ primaryDomain: string | null;
2383
+ /** @description Whitelabel toggle (default `true`). Render the "Powered by Cavuno" badge unless `false`. */
2384
+ showCavunoBranding: boolean;
2385
+ features: {
2386
+ jobAlerts: boolean;
2387
+ candidates: boolean;
2388
+ employers: boolean;
2389
+ blog: boolean;
2390
+ talentDirectory: boolean;
2391
+ registrationWall: boolean;
2392
+ passwordProtected: boolean;
2393
+ publicJobSubmission: boolean;
2394
+ candidatePaywall: boolean;
2395
+ impressum: boolean;
2396
+ };
2397
+ analytics: {
2398
+ ga4MeasurementId: string | null;
2399
+ gtmId: string | null;
2400
+ metaPixelId: string | null;
2401
+ linkedInPartnerId: string | null;
2402
+ cookieConsentRequired: boolean;
2403
+ };
2404
+ theme: {
2405
+ mode: string;
2406
+ schemeId: string;
2407
+ typography: {
2408
+ fontSans: string;
2409
+ fontHeading?: string | null;
2410
+ };
2411
+ colors: {
2412
+ light: {
2413
+ [key: string]: unknown;
2414
+ };
2415
+ dark: {
2416
+ [key: string]: unknown;
2417
+ };
2418
+ };
2419
+ } | null;
2420
+ /** @description Operator-defined custom job-field definitions (CAV-294), in display order. Board-wide; the frontend uses these to render and localize each job's opaque `customFieldValues`. Empty when the board defines none. Display-only — not filterable or searchable in v1. */
2421
+ customFields: components["schemas"]["CustomFieldDefinition"][];
2422
+ };
2423
+ PublicCompaniesSearchBody: {
2424
+ /** @description Free-text search query matched against company name. Up to 200 characters. */
2425
+ query?: string;
2426
+ /** @description Scope the results to companies in a single market (sector), by the market slug. Resolves a board-language or English slug; an unknown slug returns 404. Use `GET /boards/:identifier/companies/markets/:market` to resolve a slug to its canonical form first. */
2427
+ marketSlug?: string;
2428
+ /** @description An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results. */
2429
+ cursor?: string | null;
2430
+ /** @description A limit on the number of objects to be returned. Limit can range between 1 and 100. */
2431
+ limit?: number;
2432
+ };
2433
+ /** @description Public-only links. The admin URL is intentionally omitted on public-board responses. */
2434
+ PublicCompanyLinks: {
2435
+ /**
2436
+ * Format: uri
2437
+ * @description Canonical public URL for this company on the board, or `null` when no slug is set.
2438
+ */
2439
+ public: string | null;
2440
+ };
2441
+ PublicJob: {
2442
+ /** @description Unique identifier for the object. Use this value as the `{id}` path parameter for the job endpoints (e.g. `GET /v1/jobs/{id}`). */
2443
+ id: string;
2444
+ /**
2445
+ * @description String representing the object's type. Objects of the same type share the same value.
2446
+ * @enum {string}
2447
+ */
2448
+ object: "public_job";
2449
+ /** @description The job title. */
2450
+ title: string;
2451
+ /** @description URL-friendly slug used in public board URLs, or `null` if no slug is set. */
2452
+ slug: string | null;
2453
+ /**
2454
+ * @description Current status of the job. One of `draft`, `published`, `expired`, or `archived`.
2455
+ * @enum {string}
2456
+ */
2457
+ status: "draft" | "published" | "expired" | "archived";
2458
+ /** @description Identifier of the company the job belongs to, or `null` if no company is attached. */
2459
+ companyId: string | null;
2460
+ /**
2461
+ * @description Employment type of the role, or `null` if not specified.
2462
+ * @enum {string|null}
2463
+ */
2464
+ employmentType: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other" | null;
2465
+ /**
2466
+ * @description Whether the role is on-site, hybrid, or fully remote, or `null` if not specified.
2467
+ * @enum {string|null}
2468
+ */
2469
+ remoteOption: "on_site" | "hybrid" | "remote" | null;
2470
+ /**
2471
+ * @description Seniority level of the role, or `null` if not specified.
2472
+ * @enum {string|null}
2473
+ */
2474
+ seniority: "entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive" | null;
2475
+ /** @description Minimum salary in `salaryCurrency` units, or `null` if not specified. */
2476
+ salaryMin: number | null;
2477
+ /** @description Maximum salary in `salaryCurrency` units, or `null` if not specified. */
2478
+ salaryMax: number | null;
2479
+ /** @description Three-letter ISO 4217 currency code for the salary range, or `null` if no salary is specified. */
2480
+ salaryCurrency: string | null;
2481
+ /**
2482
+ * @description Period the salary range is quoted against, or `null` if no salary is specified.
2483
+ * @enum {string|null}
2484
+ */
2485
+ salaryTimeframe: "per_year" | "per_month" | "per_week" | "per_day" | "per_hour" | null;
2486
+ /** @description Whether the job appears in featured slots on the public board. */
2487
+ isFeatured: boolean;
2488
+ /** @description Time at which the job was first published, or `null` if not yet published. ISO 8601 datetime. */
2489
+ publishedAt: string | null;
2490
+ /** @description Time at which the job expires, or `null` if no expiry is set. ISO 8601 datetime. */
2491
+ expiresAt: string | null;
2492
+ /** @description Time at which the job was created. ISO 8601 datetime. */
2493
+ createdAt: string;
2494
+ /** @description Time at which the job was last updated. ISO 8601 datetime. */
2495
+ updatedAt: string;
2496
+ links: components["schemas"]["PublicJobLinks"];
2497
+ /** @description Long-form description of the role, or `null` if not specified. */
2498
+ description: string | null;
2499
+ /** @description Where candidates apply, or `null` if not specified. An HTTPS URL or `mailto:` URI. */
2500
+ applicationUrl: string | null;
2501
+ /** @description Hierarchical permit selection authored by the board owner. The three `remoteWorkPermit*` and `remoteWorldwide` fields are read-only derived projections. */
2502
+ remotePermits: {
2503
+ type: string;
2504
+ value: string;
2505
+ }[];
2506
+ /** @description Read-only — derived from `remotePermits`. `true` only when the authored selection is a single `{type:"worldwide"}` entry. */
2507
+ remoteWorldwide: boolean | null;
2508
+ /** @description Hierarchical timezone selection. The flat `remoteAllowedTzOffsets` field below is the read-only derived projection. */
2509
+ remoteTimezones: {
2510
+ type: string;
2511
+ value: string;
2512
+ plusMinus?: number;
2513
+ }[];
2514
+ /** @description Read-only — derived from `remoteTimezones`. UTC hour offsets used by the job-search index. */
2515
+ remoteAllowedTzOffsets: number[];
2516
+ /** @description Read-only — derived from `remotePermits` (hierarchical groups fan out to alpha2 sets; subdivisions auto-add the parent country). ISO 3166-1 alpha-2 codes. */
2517
+ remoteWorkPermitCountryCodes: string[];
2518
+ /** @description Read-only — derived from `remotePermits` (subdivision entries only). ISO 3166-2 codes. */
2519
+ remoteWorkPermitSubdivisionCodes: string[];
2520
+ /**
2521
+ * @description Whether the employer sponsors visas for remote candidates. One of `yes`, `no`, or `unknown`.
2522
+ * @enum {string}
2523
+ */
2524
+ remoteSponsorship: "yes" | "no" | "unknown";
2525
+ /** @description Required education credentials. Each value is one of `high_school`, `associate_degree`, `bachelor_degree`, `professional_certificate`, `postgraduate_degree`, or `no_requirements`. */
2526
+ educationRequirements: ("high_school" | "associate_degree" | "bachelor_degree" | "professional_certificate" | "postgraduate_degree" | "no_requirements")[];
2527
+ /** @description Minimum required experience in months, or `null` if not specified. */
2528
+ experienceMonths: number | null;
2529
+ /** @description If `true`, equivalent experience may substitute for the listed education requirements. `null` if not specified. */
2530
+ experienceInPlaceOfEducation: boolean | null;
2531
+ /**
2532
+ * @description Period denominator for `inOfficeFrequency`, or `null` if not specified.
2533
+ * @enum {string|null}
2534
+ */
2535
+ inOfficePeriod: "per_week" | "per_month" | "per_year" | null;
2536
+ /** @description How often the candidate must be in-office over `inOfficePeriod`, or `null` if not specified. */
2537
+ inOfficeFrequency: number | null;
2538
+ company: components["schemas"]["JobCompany"];
2539
+ /** @description Physical office locations associated with the job. */
2540
+ officeLocations: components["schemas"]["JobOfficeLocation"][];
2541
+ /** @description Resolved job categories (slug + board display name) — same shape as the card; names joined server-side. */
2542
+ categories: {
2543
+ slug: string;
2544
+ name: string;
2545
+ }[];
2546
+ /** @description Resolved job skills (slug + board display name). */
2547
+ skills: {
2548
+ slug: string;
2549
+ name: string;
2550
+ }[];
2551
+ /** @description Place ancestor chain (country → region → city) for the breadcrumb; each `{slug,name}` links to `/jobs/locations/:slug`. Source-language. */
2552
+ placeHierarchy: {
2553
+ slug: string;
2554
+ name: string;
2555
+ }[];
2556
+ /** @description Opaque, display-only custom-field values (CAV-294), keyed by each field's `key`. Values are the option `key`(s) for select fields, or the raw boolean/number/text otherwise — resolve labels via the board's `customFields` definitions (see `GET /v1/boards/:identifier`). `{}` when the board defines no custom fields. Not filterable or searchable in v1. */
2557
+ customFieldValues: {
2558
+ [key: string]: string | string[] | boolean | number;
2559
+ };
2560
+ };
2561
+ PublicJobAlertConfirmation: {
2562
+ /** @enum {string} */
2563
+ object: "job_alert_confirmation";
2564
+ /**
2565
+ * @description Outcome of the confirmation. Always returned with HTTP 200 so the consumer renders by status (the token may be valid, stale, or unknown).
2566
+ * @enum {string}
2567
+ */
2568
+ status: "confirmed" | "already_confirmed" | "expired" | "not_found";
2569
+ };
2570
+ PublicJobAlertManageResult: {
2571
+ /** @enum {string} */
2572
+ object: "job_alert_manage_result";
2573
+ success: boolean;
2574
+ };
2575
+ PublicJobAlertManageState: {
2576
+ /** @enum {string} */
2577
+ object: "job_alert_manage_state";
2578
+ email: string;
2579
+ confirmed: boolean;
2580
+ unsubscribed: boolean;
2581
+ preferences: {
2582
+ id: string;
2583
+ label: string | null;
2584
+ frequency: string;
2585
+ isActive: boolean;
2586
+ filters: {
2587
+ jobFunctions?: string[];
2588
+ seniorityLevels?: string[];
2589
+ remoteOptions?: string[];
2590
+ placeIds?: string[];
2591
+ salaryMin?: number | null;
2592
+ salaryMax?: number | null;
2593
+ salaryCurrency?: string | null;
2594
+ };
2595
+ manageToken: string;
2596
+ }[];
2597
+ };
2598
+ PublicJobAlertResend: {
2599
+ /** @enum {string} */
2600
+ object: "job_alert_confirmation_resend";
2601
+ /** @enum {string} */
2602
+ status: "sent" | "not_found" | "already_confirmed" | "throttled" | "send_failed";
2603
+ };
2604
+ PublicJobAlertSubscription: {
2605
+ /** @enum {string} */
2606
+ object: "job_alert_subscription";
2607
+ /**
2608
+ * @description `created` on a new subscription; `duplicate` if it existed.
2609
+ * @enum {string}
2610
+ */
2611
+ status: "created" | "duplicate";
2612
+ /** @description True when a double-opt-in confirmation email was sent. */
2613
+ requiresConfirmation: boolean;
2614
+ /** @description True if the subscriber was already email-confirmed. */
2615
+ confirmed: boolean;
2616
+ };
2617
+ PublicJobCard: {
2618
+ id: string;
2619
+ /** @enum {string} */
2620
+ object: "job_card";
2621
+ slug: string;
2622
+ title: string;
2623
+ /**
2624
+ * Format: date-time
2625
+ * @description ISO 8601 publish timestamp, or `null` if unpublished.
2626
+ */
2627
+ publishedAt: string | null;
2628
+ /** @enum {string|null} */
2629
+ employmentType: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other" | null;
2630
+ /** @enum {string|null} */
2631
+ remoteOption: "on_site" | "hybrid" | "remote" | null;
2632
+ /** @description Display region label for remote jobs (e.g. "United States", "Worldwide"); `null` for non-remote jobs. */
2633
+ remoteLocationLabel: string | null;
2634
+ salaryMin: number | null;
2635
+ salaryMax: number | null;
2636
+ salaryCurrency: string | null;
2637
+ salaryTimeframe: string | null;
2638
+ isFeatured: boolean;
2639
+ locationLabel: string | null;
2640
+ /** @description Embedded company summary, or `null` if none is attached. */
2641
+ company: {
2642
+ slug: string;
2643
+ name: string;
2644
+ logoUrl: string | null;
2645
+ } | null;
2646
+ categories: {
2647
+ slug: string;
2648
+ name: string;
2649
+ }[];
2650
+ skills: {
2651
+ slug: string;
2652
+ name: string;
2653
+ }[];
2654
+ links: {
2655
+ /**
2656
+ * Format: uri
2657
+ * @description Canonical public URL for this job, or `null` when no stable URL can be assembled.
2658
+ */
2659
+ public: string | null;
2660
+ };
2661
+ /** @description Long-form description (HTML), or `null`. Present ONLY when requested via `?fields=+description`; absent on the default slim card. */
2662
+ description?: string | null;
2663
+ };
2664
+ /** @description Public-only links. The admin URL is intentionally omitted on public-board responses. */
2665
+ PublicJobLinks: {
2666
+ /**
2667
+ * Format: uri
2668
+ * @description Canonical public URL for this job, or `null` when the job has no slug or no associated company slug (so a stable URL cannot be assembled).
2669
+ */
2670
+ public: string | null;
2671
+ };
2672
+ PublicPlace: {
2673
+ /** @enum {string} */
2674
+ object: "place";
2675
+ /** @description Stable place identity (locations-tree edge endpoint). */
2676
+ id: string;
2677
+ /** @description Parent place's `id`; `null` for a root place. */
2678
+ parentId: string | null;
2679
+ /** @description Public slug (links to `/jobs/locations/:slug`); `null` if unslugged. */
2680
+ slug: string | null;
2681
+ name: string;
2682
+ placeType: string;
2683
+ countryCode: string | null;
2684
+ regionCode: string | null;
2685
+ /** @description Live published-job count for this place. */
2686
+ jobCount: number;
2687
+ };
2688
+ PublicSearchJobsBody: {
2689
+ /** @description Free-text search query matched against job title and description. Up to 200 characters. */
2690
+ query?: string;
2691
+ /**
2692
+ * @description Result ordering. `relevance` (default) ranks by search relevance with featured jobs first; `newest` orders by publish date and `salary_high` by salary (no-salary jobs last). Any explicit sort unpins featured jobs.
2693
+ * @enum {string}
2694
+ */
2695
+ sort?: "relevance" | "newest" | "salary_high";
2696
+ /** @description Optional faceted filters to narrow search results. Multi-value filters match jobs in any of the supplied values; range filters accept `gte` and `lte` bounds. */
2697
+ filters?: {
2698
+ /** @description Only return jobs at any of the given company IDs. Up to 10 values. */
2699
+ companyId?: string[];
2700
+ /** @description Only return jobs with any of the given remote-work options. Up to 10 values. */
2701
+ remoteOption?: ("on_site" | "hybrid" | "remote")[];
2702
+ /** @description Only return jobs with any of the given employment types. Up to 10 values. */
2703
+ employmentType?: ("full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other")[];
2704
+ /** @description Only return jobs at any of the given seniority levels. Up to 10 values. */
2705
+ seniority?: ("entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive")[];
2706
+ /** @description Range filter on the job's `publishedAt` timestamp. */
2707
+ publishedAt?: {
2708
+ /**
2709
+ * Format: date-time
2710
+ * @description Only return jobs published at or after this ISO 8601 datetime.
2711
+ */
2712
+ gte?: string;
2713
+ /**
2714
+ * Format: date-time
2715
+ * @description Only return jobs published at or before this ISO 8601 datetime.
2716
+ */
2717
+ lte?: string;
2718
+ };
2719
+ /** @description Only return jobs near the place with this slug (geo radius search). Unresolvable slugs are ignored. */
2720
+ location?: string;
2721
+ /** @description Search radius in kilometres around `location` (10–250; default 50). Ignored without `location`. */
2722
+ radius?: number;
2723
+ };
2724
+ /** @description An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results. */
2725
+ cursor?: string;
2726
+ /**
2727
+ * @description A limit on the number of objects to be returned. Limit can range between 1 and 100.
2728
+ * @example 20
2729
+ */
2730
+ limit?: number;
2731
+ /**
2732
+ * @description The number of jobs to skip — the storefront page offset. Takes precedence over `cursor`. `offset + limit` may not exceed 10,000.
2733
+ * @example 0
2734
+ */
2735
+ offset?: number;
2736
+ };
2737
+ PublicTaxonomyResolution: {
2738
+ /** @enum {string} */
2739
+ object: "taxonomy_resolution";
2740
+ /** @enum {string} */
2741
+ type: "category" | "skill" | "place" | "market";
2742
+ /** @description Immutable English source slug — the semantic-search key. */
2743
+ sourceSlug: string;
2744
+ /** @description Board-language URL slug (the `<link rel=canonical>` target). */
2745
+ canonicalSlug: string;
2746
+ /** @description Board-language display name. */
2747
+ displayName: string;
2748
+ /** @description The canonical slug to emit a 308 redirect to when the inbound slug differs; `null` otherwise. */
2749
+ redirectTo: string | null;
2750
+ geo: components["schemas"]["TaxonomyGeo"];
2751
+ };
2752
+ PublicVerifyBoardPasswordBody: {
2753
+ /** @description The board password. */
2754
+ password: string;
2755
+ };
2756
+ PublishJobBody: {
2757
+ /**
2758
+ * Format: date-time
2759
+ * @description New expiry as an ISO 8601 datetime. Pass `null` to clear the expiry. When omitted, the server preserves the existing expiry **if it is still in the future**; a stored expiry in the past (e.g. left over from a prior `expire` call) is cleared automatically so a republished job does not land in an immediately-invisible state.
2760
+ */
2761
+ expiresAt?: string | null;
2762
+ };
2763
+ ReadReceipt: {
2764
+ /** @enum {string} */
2765
+ object: "read_receipt";
2766
+ /** Format: date-time */
2767
+ markedAt: string;
2768
+ };
2769
+ RedirectResolution: {
2770
+ /** @enum {string} */
2771
+ object: "redirect_resolution";
2772
+ path: string;
2773
+ /** @description The redirect target (board-relative), or `null` when no redirect matches. The consumer 308s to `target`, or 404s when `null`. */
2774
+ target: string | null;
2775
+ };
2776
+ RemotePermitTaxonomyEntry: {
2777
+ /** @description Discriminator. One of: `worldwide`, `world_region`, `continent`, `region`, `subregion`, `custom`, `country`, `subdivision`. */
2778
+ type: string;
2779
+ /** @description Canonical value for the type. ISO 3166-1 alpha-2 for `country`, ISO 3166-2 for `subdivision`, etc. */
2780
+ value: string;
2781
+ /** @description Human-readable display label. */
2782
+ label: string;
2783
+ };
2784
+ RemoteTimezoneTaxonomyEntry: {
2785
+ /** @description Discriminator. One of: `all`, `world_region`, `continent`, `region`, `subregion`, `country`, `timezone`. */
2786
+ type: string;
2787
+ /** @description Canonical value for the type. ISO 3166-1 alpha-2 for `country`, IANA name (e.g. `Europe/London`) for `timezone`, etc. */
2788
+ value: string;
2789
+ /** @description Human-readable display label. */
2790
+ label: string;
2791
+ };
2792
+ ReorderPipelineStagesBody: {
2793
+ /** @description The job whose stages are reordered. */
2794
+ jobId: string;
2795
+ /** @description Every stage id of the job, in the new order. */
2796
+ orderedStageIds: string[];
2797
+ };
2798
+ ReplyBody: {
2799
+ body: string;
2800
+ };
2801
+ ReportBody: {
2802
+ /** @enum {string} */
2803
+ reason: "spam" | "harassment" | "misrepresentation" | "other";
2804
+ freeText?: string;
2805
+ };
2806
+ ResourceLinks: {
2807
+ /**
2808
+ * Format: uri
2809
+ * @description Canonical public URL for this resource on the board. Honours the configured custom domain when present, otherwise uses the board subdomain.
2810
+ */
2811
+ public: string;
2812
+ /**
2813
+ * Format: uri
2814
+ * @description URL inside the Cavuno app where the authenticated owner can manage this resource.
2815
+ */
2816
+ admin: string;
2817
+ };
2818
+ Resume: {
2819
+ /** @enum {string} */
2820
+ object: "resume";
2821
+ /**
2822
+ * @description Async parse state; poll GET /me/resume until parsed or failed.
2823
+ * @enum {string|null}
2824
+ */
2825
+ parseStatus: "parsing" | "parsed" | "failed" | null;
2826
+ parseFailureReason: string | null;
2827
+ /** Format: date-time */
2828
+ parsedAt: string | null;
2829
+ keepResumeOnFile: boolean | null;
2830
+ hasResumeOnFile: boolean;
2831
+ file: {
2832
+ /** @description Short-lived signed download URL. */
2833
+ url: string;
2834
+ contentType: string;
2835
+ sizeBytes: number;
2836
+ } | null;
2837
+ };
2838
+ RevokeRequest: {
2839
+ /** @description The access or refresh token to revoke. */
2840
+ token: string;
2841
+ /**
2842
+ * @description Hint indicating whether `token` is an `access_token` or `refresh_token`. Optional.
2843
+ * @enum {string}
2844
+ */
2845
+ token_type_hint?: "access_token" | "refresh_token";
2846
+ /** @description OAuth client identifier. May be supplied here or via HTTP Basic authentication. */
2847
+ client_id?: string;
2848
+ /** @description OAuth client secret. May be supplied here or via HTTP Basic authentication. */
2849
+ client_secret?: string;
2850
+ };
2851
+ SalaryCompanyIndexItem: {
2852
+ /** @enum {string} */
2853
+ object: "salary_company";
2854
+ companySlug: string;
2855
+ companyName: string;
2856
+ logoPath: string | null;
2857
+ avgSalaryMin: number;
2858
+ avgSalaryMax: number;
2859
+ jobCount: number;
2860
+ currency: string;
2861
+ };
2862
+ SalaryLocationIndexItem: {
2863
+ /** @enum {string} */
2864
+ object: "salary_location";
2865
+ placeSlug: string;
2866
+ placeName: string;
2867
+ /** @description Slug of the parent place; `null` for a top-level node. */
2868
+ parentSlug: string | null;
2869
+ avgSalaryMin: number;
2870
+ avgSalaryMax: number;
2871
+ jobCount: number;
2872
+ };
2873
+ SalarySkillIndexItem: {
2874
+ /** @enum {string} */
2875
+ object: "salary_skill";
2876
+ slug: string;
2877
+ name: string;
2878
+ avgSalaryMin: number;
2879
+ avgSalaryMax: number;
2880
+ p25SalaryMin: number;
2881
+ p75SalaryMax: number;
2882
+ jobCount: number;
2883
+ currency: string;
2884
+ };
2885
+ SalaryTitleIndexItem: {
2886
+ /** @enum {string} */
2887
+ object: "salary_title";
2888
+ slug: string;
2889
+ name: string;
2890
+ avgSalaryMin: number;
2891
+ avgSalaryMax: number;
2892
+ p25SalaryMin: number;
2893
+ p75SalaryMax: number;
2894
+ jobCount: number;
2895
+ currency: string;
2896
+ };
2897
+ SalesLedPlan: {
2898
+ /** @enum {string} */
2899
+ object: "sales_led_plan";
2900
+ id: string;
2901
+ name: string;
2902
+ description: string;
2903
+ /** @description Display price text, e.g. "Contact us". */
2904
+ priceText: string;
2905
+ ctaText: string;
2906
+ /** @description The CTA target — a URL, mailto:, or tel: link. */
2907
+ ctaDestination: string;
2908
+ featuredBullets: string[];
2909
+ displayOrder: number;
2910
+ };
2911
+ SaveJobBody: {
2912
+ jobId: string;
2913
+ };
2914
+ SavedJob: {
2915
+ /** @description Saved-job row ID. */
2916
+ id: string;
2917
+ /** @enum {string} */
2918
+ object: "saved_job";
2919
+ /** @description The saved job — also the DELETE path key. */
2920
+ jobId: string;
2921
+ /** Format: date-time */
2922
+ savedAt: string;
2923
+ job: components["schemas"]["PublicJob"];
2924
+ };
2925
+ SearchBlogPostsBody: {
2926
+ query?: string;
2927
+ /** @enum {string} */
2928
+ status?: "draft" | "scheduled" | "published";
2929
+ cursor?: string | null;
2930
+ limit?: number;
2931
+ };
2932
+ SearchCompaniesBody: {
2933
+ /** @description Free-text search query matched against company name. Up to 200 characters. */
2934
+ query?: string;
2935
+ /** @description An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results. */
2936
+ cursor?: string | null;
2937
+ /**
2938
+ * @description A limit on the number of objects to be returned. Limit can range between 1 and 100.
2939
+ * @example 20
2940
+ */
2941
+ limit?: number;
2942
+ };
2943
+ SearchJobsBody: {
2944
+ /** @description Free-text search query matched against job title and description. Up to 200 characters. */
2945
+ query?: string;
2946
+ /** @description Optional faceted filters to narrow search results. Multi-value filters match jobs in any of the supplied values; range filters accept `gte` and `lte` bounds. */
2947
+ filters?: {
2948
+ /** @description Only return jobs in any of the given statuses. Up to 10 values. */
2949
+ status?: ("draft" | "published" | "expired" | "archived")[];
2950
+ /** @description Only return jobs at any of the given company IDs. Up to 10 values. */
2951
+ companyId?: string[];
2952
+ /** @description Only return jobs with any of the given remote-work options. Up to 10 values. */
2953
+ remoteOption?: ("on_site" | "hybrid" | "remote")[];
2954
+ /** @description Only return jobs with any of the given employment types. Up to 10 values. */
2955
+ employmentType?: ("full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other")[];
2956
+ /** @description Only return jobs at any of the given seniority levels. Up to 10 values. */
2957
+ seniority?: ("entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive")[];
2958
+ /** @description Range filter on the job's `publishedAt` timestamp. */
2959
+ publishedAt?: {
2960
+ /**
2961
+ * Format: date-time
2962
+ * @description Only return jobs published at or after this ISO 8601 datetime.
2963
+ */
2964
+ gte?: string;
2965
+ /**
2966
+ * Format: date-time
2967
+ * @description Only return jobs published at or before this ISO 8601 datetime.
2968
+ */
2969
+ lte?: string;
2970
+ };
2971
+ };
2972
+ /** @description An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results. */
2973
+ cursor?: string;
2974
+ /**
2975
+ * @description A limit on the number of objects to be returned. Limit can range between 1 and 100.
2976
+ * @example 20
2977
+ */
2978
+ limit?: number;
2979
+ };
2980
+ SendWorkEmailBody: {
2981
+ /** Format: email */
2982
+ workEmail: string;
2983
+ };
2984
+ SettingsAdsenseBody: {
2985
+ /** @description Whether AdSense placements are rendered on the public board. */
2986
+ adsenseEnabled?: boolean;
2987
+ /** @description AdSense publisher ID in `ca-pub-XXXXXXXXXXXXXXXX` format. Pass an empty string or `null` to clear. */
2988
+ adsenseClientId?: string | "" | unknown | unknown;
2989
+ /** @description Map of placement key to slot configuration. Placement keys are lowercase alphanumeric with `-`, `_`, `.`, or `:`. */
2990
+ adsenseSlots?: {
2991
+ [key: string]: components["schemas"]["SettingsAdsenseSlot"];
2992
+ };
2993
+ /** @description Contents to serve from `/ads.txt`. Up to 2,000 characters. Pass an empty string or `null` to clear. */
2994
+ adsTxt?: string | "" | unknown | unknown;
2995
+ };
2996
+ SettingsAdsenseSlot: {
2997
+ /** @description Whether this placement is rendered. */
2998
+ enabled: boolean;
2999
+ /** @description Ten-digit AdSense slot ID. Pass an empty string or `null` to clear. */
3000
+ slotId: string | "" | unknown | unknown;
3001
+ /** @description AdSense layout type for the placement. */
3002
+ layout?: ("auto" | "in-article" | "in-feed" | "fluid") | "" | unknown | unknown;
3003
+ /** @description AdSense ad format. */
3004
+ format?: ("auto" | "horizontal" | "vertical" | "rectangle" | "responsive") | "" | unknown | unknown;
3005
+ /** @description Visual style override for the placement. */
3006
+ style?: ("default" | "light" | "dark" | "contrast") | "" | unknown | unknown;
3007
+ /** @description How often the placement is shown (e.g. once every N items). */
3008
+ frequency?: number | unknown | unknown;
3009
+ };
3010
+ SettingsPasswordProtectionBody: {
3011
+ /** @description Plaintext password used to gate the public board. Must be at least 8 characters. Stored hashed and encrypted server-side. */
3012
+ password: string;
3013
+ };
3014
+ SettingsPaywallBody: {
3015
+ /** @description Whether the job-access paywall is enforced on the public board. */
3016
+ jobAccessPaywallEnabled: boolean;
3017
+ /** @description Number of jobs visible before the paywall locks the rest. Range 1–500. */
3018
+ jobAccessPreviewCount?: number;
3019
+ /** @description Heading shown on the paywall. Up to 120 characters. */
3020
+ jobAccessLockHeading?: string;
3021
+ /** @description Body copy shown on the paywall. Up to 600 characters. */
3022
+ jobAccessLockDescription?: string;
3023
+ /** @description Call-to-action label shown on the paywall. Up to 60 characters. */
3024
+ jobAccessButtonText?: string;
3025
+ /** @description Fine-print disclaimer shown beneath the call-to-action. Up to 200 characters. */
3026
+ jobAccessDisclaimerText?: string;
3027
+ /** @description Label appended to the monthly price (e.g. `/month`). Up to 60 characters. */
3028
+ jobAccessPerMonthLabel?: string;
3029
+ /** @description Template string used to render the savings line for annual plans. Up to 120 characters. */
3030
+ jobAccessSavingsTemplate?: string;
3031
+ /** @description Three-letter ISO 4217 currency code for paywall pricing. */
3032
+ jobAccessCurrency?: string;
3033
+ /** @description Stripe product ID associated with the paywall plan. Pass `null` to clear. */
3034
+ jobAccessStripeProductId?: string | unknown | unknown;
3035
+ /** @description Stripe billing-portal configuration ID used for self-serve plan management. Pass `null` to clear. */
3036
+ jobAccessStripePortalConfigId?: string | unknown | unknown;
3037
+ };
3038
+ SkillLocationSalary: {
3039
+ /** @enum {string} */
3040
+ object: "skill_location_salary";
3041
+ skillSourceSlug: string;
3042
+ skillCanonicalSlug: string;
3043
+ locationSourceSlug: string;
3044
+ locationCanonicalSlug: string;
3045
+ skillName: string;
3046
+ placeName: string;
3047
+ countryCode: string;
3048
+ adminLevel: string;
3049
+ overallSalary: {
3050
+ avgMin: number;
3051
+ avgMax: number;
3052
+ p25Min: number | null;
3053
+ p75Max: number | null;
3054
+ jobCount: number;
3055
+ } | null;
3056
+ bySeniority: {
3057
+ seniority: string;
3058
+ avgSalaryMin: number;
3059
+ avgSalaryMax: number;
3060
+ jobCount: number;
3061
+ }[];
3062
+ childLocations: {
3063
+ placeSlug: string;
3064
+ placeName: string;
3065
+ avgSalaryMin: number;
3066
+ avgSalaryMax: number;
3067
+ jobCount: number;
3068
+ }[];
3069
+ childLocationsByRegion: {
3070
+ regionName: string;
3071
+ regionSlug: string;
3072
+ cities: {
3073
+ placeSlug: string;
3074
+ placeName: string;
3075
+ avgSalaryMin: number;
3076
+ avgSalaryMax: number;
3077
+ jobCount: number;
3078
+ }[];
3079
+ }[];
3080
+ otherLocations: {
3081
+ placeSlug: string;
3082
+ placeName: string;
3083
+ avgSalaryMin: number;
3084
+ avgSalaryMax: number;
3085
+ jobCount: number;
3086
+ }[];
3087
+ topSkills: {
3088
+ avgSalaryMin: number;
3089
+ avgSalaryMax: number;
3090
+ jobCount: number;
3091
+ skillSlug: string;
3092
+ skillName: string;
3093
+ }[];
3094
+ topTitles: {
3095
+ avgSalaryMin: number;
3096
+ avgSalaryMax: number;
3097
+ jobCount: number;
3098
+ categorySlug: string;
3099
+ categoryName: string;
3100
+ }[];
3101
+ boardSkillAvgMin: number | null;
3102
+ boardSkillAvgMax: number | null;
3103
+ currency: string;
3104
+ };
3105
+ SkillLocationsIndex: {
3106
+ /** @enum {string} */
3107
+ object: "skill_locations_index";
3108
+ sourceSlug: string;
3109
+ canonicalSlug: string;
3110
+ skillName: string;
3111
+ currency: string;
3112
+ locations: components["schemas"]["SalaryLocationIndexItem"][];
3113
+ };
3114
+ SkillSalaryDetail: {
3115
+ /** @enum {string} */
3116
+ object: "skill_salary_detail";
3117
+ /** @description Immutable English source slug — the salary-stats key. */
3118
+ sourceSlug: string;
3119
+ /** @description Board-language canonical URL slug — the starter 308 target. */
3120
+ canonicalSlug: string;
3121
+ skillName: string;
3122
+ overallSalary: {
3123
+ avgMin: number;
3124
+ avgMax: number;
3125
+ medianMin: number;
3126
+ medianMax: number;
3127
+ p25Min: number;
3128
+ p75Max: number;
3129
+ jobCount: number;
3130
+ } | null;
3131
+ bySeniority: {
3132
+ seniority: string;
3133
+ avgSalaryMin: number;
3134
+ avgSalaryMax: number;
3135
+ jobCount: number;
3136
+ boardAvgMin: number | null;
3137
+ boardAvgMax: number | null;
3138
+ diffPercent: number | null;
3139
+ }[];
3140
+ topCompanies: {
3141
+ avgSalaryMin: number;
3142
+ avgSalaryMax: number;
3143
+ jobCount: number;
3144
+ companySlug: string;
3145
+ companyName: string;
3146
+ logoPath: string | null;
3147
+ }[];
3148
+ topLocations: {
3149
+ avgSalaryMin: number;
3150
+ avgSalaryMax: number;
3151
+ jobCount: number;
3152
+ placeName: string;
3153
+ placeSlug: string;
3154
+ countryCode: string;
3155
+ }[];
3156
+ topTitles: {
3157
+ avgSalaryMin: number;
3158
+ avgSalaryMax: number;
3159
+ jobCount: number;
3160
+ categorySlug: string;
3161
+ categoryName: string;
3162
+ }[];
3163
+ relatedSkills: {
3164
+ avgSalaryMin: number;
3165
+ avgSalaryMax: number;
3166
+ jobCount: number;
3167
+ skillSlug: string;
3168
+ skillName: string;
3169
+ }[];
3170
+ totalLocationCount: number;
3171
+ boardOverallAvgMin: number | null;
3172
+ boardOverallAvgMax: number | null;
3173
+ boardMedianMin: number | null;
3174
+ boardMedianMax: number | null;
3175
+ currency: string;
3176
+ };
3177
+ StartAboutApplicationBody: {
3178
+ applicationId: string;
3179
+ body: string;
3180
+ };
3181
+ StartConversationBody: {
3182
+ candidateBoardUserId: string;
3183
+ body: string;
3184
+ };
3185
+ TalentDirectoryEntry: {
3186
+ /** @enum {string} */
3187
+ object: "talent_directory_entry";
3188
+ handle: string | null;
3189
+ displayName: string | null;
3190
+ headline: string | null;
3191
+ location: string | null;
3192
+ avatarUrl: string | null;
3193
+ bio: string | null;
3194
+ jobSearchStatus: string | null;
3195
+ skills: string[];
3196
+ experiences: {
3197
+ title: string;
3198
+ companyName: string;
3199
+ startDate: string;
3200
+ endDate: string | null;
3201
+ }[];
3202
+ education: {
3203
+ institutionName: string;
3204
+ startDate: string | null;
3205
+ endDate: string | null;
3206
+ }[];
3207
+ };
3208
+ TalentProfile: {
3209
+ /** @enum {string} */
3210
+ object: "talent_profile";
3211
+ handle: string | null;
3212
+ displayName: string | null;
3213
+ headline: string | null;
3214
+ location: string | null;
3215
+ bio: string | null;
3216
+ avatarUrl: string | null;
3217
+ /** @description The candidate job-search status, or `null` when it is set to employers-only (an anonymous caller is not an employer). */
3218
+ jobSearchStatus: string | null;
3219
+ experiences: {
3220
+ title: string;
3221
+ companyName: string;
3222
+ companyUrl: string | null;
3223
+ location: string | null;
3224
+ employmentType: string | null;
3225
+ locationType: string | null;
3226
+ foundVia: string | null;
3227
+ /** @description Start month, `YYYY-MM`. */
3228
+ startDate: string;
3229
+ /** @description End month `YYYY-MM`, or `null` for a current role. */
3230
+ endDate: string | null;
3231
+ description: string | null;
3232
+ /** @description Skills the candidate applied in this role. */
3233
+ experienceSkills: string[];
3234
+ }[];
3235
+ education: {
3236
+ institutionName: string;
3237
+ institutionUrl: string | null;
3238
+ degree: string | null;
3239
+ fieldOfStudy: string | null;
3240
+ grade: string | null;
3241
+ activitiesAndSocieties: string | null;
3242
+ startDate: string | null;
3243
+ endDate: string | null;
3244
+ description: string | null;
3245
+ }[];
3246
+ skills: {
3247
+ name: string;
3248
+ /** @description Reference to the canonical skill taxonomy, when matched. */
3249
+ jobSkillId: string | null;
3250
+ }[];
3251
+ languages: {
3252
+ name: string;
3253
+ proficiency: string;
3254
+ }[];
3255
+ };
3256
+ /** @description Geo for place resolutions; `null` for category/skill. */
3257
+ TaxonomyGeo: {
3258
+ lat: number | null;
3259
+ lng: number | null;
3260
+ countryCode: string | null;
3261
+ regionCode: string | null;
3262
+ region: string | null;
3263
+ city: string | null;
3264
+ locality: string | null;
3265
+ placeType: string | null;
3266
+ } | null;
3267
+ TitleLocationSalary: {
3268
+ /** @enum {string} */
3269
+ object: "title_location_salary";
3270
+ categorySourceSlug: string;
3271
+ categoryCanonicalSlug: string;
3272
+ locationSourceSlug: string;
3273
+ locationCanonicalSlug: string;
3274
+ categoryName: string;
3275
+ placeName: string;
3276
+ countryCode: string;
3277
+ adminLevel: string;
3278
+ overallSalary: {
3279
+ avgMin: number;
3280
+ avgMax: number;
3281
+ p25Min: number | null;
3282
+ p75Max: number | null;
3283
+ jobCount: number;
3284
+ } | null;
3285
+ bySeniority: {
3286
+ seniority: string;
3287
+ avgSalaryMin: number;
3288
+ avgSalaryMax: number;
3289
+ jobCount: number;
3290
+ }[];
3291
+ childLocations: {
3292
+ placeSlug: string;
3293
+ placeName: string;
3294
+ avgSalaryMin: number;
3295
+ avgSalaryMax: number;
3296
+ jobCount: number;
3297
+ }[];
3298
+ childLocationsByRegion: {
3299
+ regionName: string;
3300
+ regionSlug: string;
3301
+ cities: {
3302
+ placeSlug: string;
3303
+ placeName: string;
3304
+ avgSalaryMin: number;
3305
+ avgSalaryMax: number;
3306
+ jobCount: number;
3307
+ }[];
3308
+ }[];
3309
+ otherLocations: {
3310
+ placeSlug: string;
3311
+ placeName: string;
3312
+ avgSalaryMin: number;
3313
+ avgSalaryMax: number;
3314
+ jobCount: number;
3315
+ }[];
3316
+ topSkills: {
3317
+ avgSalaryMin: number;
3318
+ avgSalaryMax: number;
3319
+ jobCount: number;
3320
+ skillSlug: string;
3321
+ skillName: string;
3322
+ }[];
3323
+ topTitles: {
3324
+ avgSalaryMin: number;
3325
+ avgSalaryMax: number;
3326
+ jobCount: number;
3327
+ categorySlug: string;
3328
+ categoryName: string;
3329
+ }[];
3330
+ boardCategoryAvgMin: number | null;
3331
+ boardCategoryAvgMax: number | null;
3332
+ currency: string;
3333
+ };
3334
+ TitleLocationsIndex: {
3335
+ /** @enum {string} */
3336
+ object: "title_locations_index";
3337
+ sourceSlug: string;
3338
+ canonicalSlug: string;
3339
+ categoryName: string;
3340
+ currency: string;
3341
+ locations: components["schemas"]["SalaryLocationIndexItem"][];
3342
+ };
3343
+ TitleSalaryDetail: {
3344
+ /** @enum {string} */
3345
+ object: "title_salary_detail";
3346
+ /** @description Immutable English source slug — the salary-stats key. */
3347
+ sourceSlug: string;
3348
+ /** @description Board-language canonical URL slug — the starter 308 target. */
3349
+ canonicalSlug: string;
3350
+ categoryName: string;
3351
+ overallSalary: {
3352
+ avgMin: number;
3353
+ avgMax: number;
3354
+ p25Min: number;
3355
+ p75Max: number;
3356
+ jobCount: number;
3357
+ } | null;
3358
+ bySeniority: {
3359
+ seniority: string;
3360
+ avgSalaryMin: number;
3361
+ avgSalaryMax: number;
3362
+ jobCount: number;
3363
+ boardAvgMin: number | null;
3364
+ boardAvgMax: number | null;
3365
+ boardMedianMin: number | null;
3366
+ boardMedianMax: number | null;
3367
+ boardP25Min: number | null;
3368
+ boardP75Min: number | null;
3369
+ boardP25Max: number | null;
3370
+ boardP75Max: number | null;
3371
+ diffPercent: number | null;
3372
+ }[];
3373
+ topCompanies: {
3374
+ avgSalaryMin: number;
3375
+ avgSalaryMax: number;
3376
+ jobCount: number;
3377
+ companySlug: string;
3378
+ companyName: string;
3379
+ logoPath: string | null;
3380
+ }[];
3381
+ topLocations: {
3382
+ avgSalaryMin: number;
3383
+ avgSalaryMax: number;
3384
+ jobCount: number;
3385
+ placeName: string;
3386
+ placeSlug: string;
3387
+ countryCode: string;
3388
+ }[];
3389
+ topSkills: {
3390
+ avgSalaryMin: number;
3391
+ avgSalaryMax: number;
3392
+ jobCount: number;
3393
+ skillSlug: string;
3394
+ skillName: string;
3395
+ }[];
3396
+ relatedTitles: {
3397
+ avgSalaryMin: number;
3398
+ avgSalaryMax: number;
3399
+ jobCount: number;
3400
+ categorySlug: string;
3401
+ categoryName: string;
3402
+ }[];
3403
+ totalLocationCount: number;
3404
+ boardOverallAvgMin: number | null;
3405
+ boardOverallAvgMax: number | null;
3406
+ boardMedianMin: number | null;
3407
+ boardMedianMax: number | null;
3408
+ boardP25Min: number | null;
3409
+ boardP75Max: number | null;
3410
+ currency: string;
3411
+ };
3412
+ TokenRequest: {
3413
+ /**
3414
+ * @description OAuth grant type. Either `authorization_code` to exchange an authorization code for a new token pair, or `refresh_token` to exchange a refresh token for a new token pair.
3415
+ * @enum {string}
3416
+ */
3417
+ grant_type: "authorization_code" | "refresh_token";
3418
+ /** @description Authorization code returned from the authorization endpoint. Required when `grant_type` is `authorization_code`. */
3419
+ code?: string;
3420
+ /** @description Redirect URI used in the original authorization request. Must match exactly. Required when `grant_type` is `authorization_code`. */
3421
+ redirect_uri?: string;
3422
+ /** @description PKCE code verifier whose `S256` hash matches the original `code_challenge`. Required when `grant_type` is `authorization_code`. */
3423
+ code_verifier?: string;
3424
+ /** @description Refresh token previously issued. Required when `grant_type` is `refresh_token`. Refresh tokens are single-use; reusing one revokes the entire token chain. */
3425
+ refresh_token?: string;
3426
+ /** @description OAuth client identifier. May be supplied here or via HTTP Basic authentication. */
3427
+ client_id?: string;
3428
+ /** @description OAuth client secret. May be supplied here or via HTTP Basic authentication. */
3429
+ client_secret?: string;
3430
+ /** @description Optional scope narrowing. Currently ignored — issued tokens always carry the full scope registered for the client. */
3431
+ scope?: string;
3432
+ };
3433
+ TokenResponse: {
3434
+ /** @description Newly issued access token. Use as a `Bearer` token in the `Authorization` header. */
3435
+ access_token: string;
3436
+ /**
3437
+ * @description Always `Bearer`.
3438
+ * @enum {string}
3439
+ */
3440
+ token_type: "Bearer";
3441
+ /** @description Lifetime of the access token, in seconds. */
3442
+ expires_in: number;
3443
+ /** @description Newly issued refresh token. Single-use; reusing it revokes the entire token chain. */
3444
+ refresh_token: string;
3445
+ /** @description Space-separated list of scopes granted on the issued token. */
3446
+ scope: string;
3447
+ };
3448
+ UnreadCount: {
3449
+ /** @enum {string} */
3450
+ object: "unread_count";
3451
+ count: number;
3452
+ };
3453
+ UnsubscribeBody: {
3454
+ boardUserId: string;
3455
+ /** @enum {string} */
3456
+ channel: "messageEmails" | "applicationEmails";
3457
+ token: string;
3458
+ };
3459
+ UpdateApplicationFactsBody: {
3460
+ candidateName?: string;
3461
+ /** Format: email */
3462
+ candidateEmail?: string;
3463
+ candidateHeadline?: string;
3464
+ candidateLocation?: string;
3465
+ coverNote?: string;
3466
+ };
3467
+ UpdateAuthorBody: {
3468
+ /** @description URL-friendly slug for the author. Auto-generated from `name` when omitted. */
3469
+ slug?: string;
3470
+ /** @description Short biography for the author. Sanitized HTML. */
3471
+ bio?: string;
3472
+ /**
3473
+ * Format: email
3474
+ * @description The author's email address.
3475
+ */
3476
+ email?: string;
3477
+ /**
3478
+ * @description Author visibility status. One of `active` or `inactive`.
3479
+ * @enum {string}
3480
+ */
3481
+ status?: "active" | "inactive";
3482
+ /** @description Storage ID of an uploaded avatar image (from `POST /v1/media/upload`). Pass `null` to clear an existing avatar. */
3483
+ avatarStorageId?: string | null;
3484
+ /** @description The author's personal website URL. Normalized to a canonical URL when stored. */
3485
+ websiteUrl?: string;
3486
+ /** @description The author's X (Twitter) profile URL. Stored as the canonical `https://x.com/<handle>` URL. */
3487
+ twitterUrl?: string;
3488
+ /** @description The author's LinkedIn profile URL. */
3489
+ linkedinUrl?: string;
3490
+ /** @description The author's GitHub profile URL. */
3491
+ githubUrl?: string;
3492
+ /** @description SEO meta title for the author page. */
3493
+ metaTitle?: string;
3494
+ /** @description SEO meta description for the author page. */
3495
+ metaDescription?: string;
3496
+ /** @description The author's display name. */
3497
+ name?: string;
3498
+ };
3499
+ UpdateBlogPostBody: {
3500
+ slug?: string;
3501
+ html?: string;
3502
+ customExcerpt?: string;
3503
+ readingTimeMin?: number;
3504
+ featured?: boolean;
3505
+ authorIds?: string[];
3506
+ tagIds?: string[];
3507
+ coverStorageId?: string | null;
3508
+ ogImageStorageId?: string | null;
3509
+ featureImageAlt?: string;
3510
+ featureImageCaption?: string;
3511
+ seoTitle?: string;
3512
+ seoDescription?: string;
3513
+ /** Format: uri */
3514
+ canonicalUrl?: string;
3515
+ /** Format: date-time */
3516
+ publishedAt?: string;
3517
+ title?: string;
3518
+ /** @enum {string} */
3519
+ status?: "draft" | "scheduled" | "published";
3520
+ };
3521
+ UpdateCandidateProfileBody: {
3522
+ displayName?: string;
3523
+ bio?: string;
3524
+ handle?: string;
3525
+ headline?: string;
3526
+ location?: string;
3527
+ /** @enum {string} */
3528
+ profileVisibility?: "hidden" | "logged_in_only" | "public";
3529
+ /** @enum {string} */
3530
+ jobSearchStatus?: "actively_looking" | "open_to_offers" | "not_looking";
3531
+ /** @enum {string} */
3532
+ jobSearchStatusVisibleTo?: "everyone" | "employers_only";
3533
+ openToRelocate?: boolean;
3534
+ };
3535
+ UpdateCompanyBody: {
3536
+ /** @description Public company website URL. Normalized to a canonical apex domain when stored. */
3537
+ website?: string;
3538
+ /** @description One-line summary of the company. Up to 280 characters. */
3539
+ summary?: string;
3540
+ /** @description Long-form description of the company. Up to 25,000 characters. */
3541
+ description?: string;
3542
+ /** @description X (Twitter) profile URL or handle. Stored as the canonical handle. */
3543
+ xUrl?: string;
3544
+ /** @description LinkedIn company page URL. */
3545
+ linkedinUrl?: string;
3546
+ /** @description Facebook company page URL. */
3547
+ facebookUrl?: string;
3548
+ /** @description The company's display name. */
3549
+ name?: string;
3550
+ /** @description URL-friendly slug for the company. */
3551
+ slug?: string;
3552
+ };
3553
+ UpdateEducationBody: {
3554
+ institutionName?: string;
3555
+ institutionUrl?: string;
3556
+ degree?: string;
3557
+ fieldOfStudy?: string;
3558
+ grade?: string;
3559
+ activitiesAndSocieties?: string;
3560
+ startDate?: string;
3561
+ endDate?: string;
3562
+ description?: string;
3563
+ sortOrder?: number;
3564
+ };
3565
+ UpdateEmployerCompanyBody: {
3566
+ name?: string;
3567
+ description?: string;
3568
+ website?: string;
3569
+ summary?: string;
3570
+ xUrl?: string;
3571
+ linkedinUrl?: string;
3572
+ facebookUrl?: string;
3573
+ };
3574
+ UpdateExperienceBody: {
3575
+ title?: string;
3576
+ companyName?: string;
3577
+ startDate?: string;
3578
+ companyUrl?: string;
3579
+ location?: string;
3580
+ employmentType?: string;
3581
+ locationType?: string;
3582
+ foundVia?: string;
3583
+ endDate?: string;
3584
+ description?: string;
3585
+ sortOrder?: number;
3586
+ };
3587
+ UpdateJobBody: {
3588
+ /** @description Identifier of the company the job belongs to. */
3589
+ companyId?: string;
3590
+ /** @description Long-form description of the role. Up to 25,000 characters. */
3591
+ description?: string;
3592
+ /** @description URL-friendly slug for the job. Auto-generated from `title` when omitted. */
3593
+ slug?: string;
3594
+ /**
3595
+ * @description Employment type of the role.
3596
+ * @enum {string}
3597
+ */
3598
+ employmentType?: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other";
3599
+ /**
3600
+ * @description Whether the role is on-site, hybrid, or fully remote.
3601
+ * @enum {string}
3602
+ */
3603
+ remoteOption?: "on_site" | "hybrid" | "remote";
3604
+ /** @description Where remote candidates must hold work authorization. Each entry is the smallest relevant scope: `worldwide`, a `world_region` (EMEA / LATAM / NA / APAC), a `continent`, a `region`, a `subregion`, a `custom` group (e.g. `EU`), a `country` (ISO 3166-1 alpha-2), or a `subdivision` (ISO 3166-2). Subdivisions auto-imply their parent country in the derived `remoteWorkPermitCountryCodes` output. Worldwide is mutually exclusive with all other entries. The canonical `{type, value}` set is published at `GET /v1/taxonomies/remote-permits`. Pass `[]` to clear an existing constraint. */
3605
+ remotePermits?: {
3606
+ /** @enum {string} */
3607
+ type: "worldwide" | "world_region" | "continent" | "region" | "subregion" | "subdivision" | "country" | "custom";
3608
+ value: string;
3609
+ }[];
3610
+ /** @description Where remote candidates must be timezone-compatible. Each entry mirrors the `remotePermits` shape (`world_region`, `continent`, `region`, `subregion`, `country`) plus `timezone` (specific IANA name with optional `plusMinus` ±N hours expansion) and `all` (every timezone — equivalent of `worldwide` for permits). The canonical `{type, value}` set is published at `GET /v1/taxonomies/remote-timezones`. **When omitted on POST**, the server auto-derives this from `remotePermits` (or `[{all,all}]` if neither was provided). **PATCH never auto-re-derives** — once set, only an explicit replacement updates the stored value, even when `remotePermits` changes. Pass `[]` to clear an existing constraint. */
3611
+ remoteTimezones?: {
3612
+ /** @enum {string} */
3613
+ type: "all" | "world_region" | "continent" | "region" | "subregion" | "country" | "timezone";
3614
+ value: string;
3615
+ plusMinus?: number;
3616
+ }[];
3617
+ /**
3618
+ * @description Whether the employer sponsors visas for remote candidates. One of `yes`, `no`, or `unknown`.
3619
+ * @enum {string}
3620
+ */
3621
+ remoteSponsorship?: "yes" | "no" | "unknown";
3622
+ /**
3623
+ * @description Seniority level of the role.
3624
+ * @enum {string}
3625
+ */
3626
+ seniority?: "entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive";
3627
+ /** @description Where candidates apply. Accepts an HTTPS URL, a `mailto:` URI, or a bare email address (which is normalized to `mailto:` form). */
3628
+ applicationUrl?: string;
3629
+ /** @description Minimum salary, in `salaryCurrency` units. */
3630
+ salaryMin?: number;
3631
+ /** @description Maximum salary, in `salaryCurrency` units. */
3632
+ salaryMax?: number;
3633
+ /** @description Three-letter ISO 4217 currency code for `salaryMin` and `salaryMax`. */
3634
+ salaryCurrency?: string;
3635
+ /**
3636
+ * @description Period the `salaryMin` and `salaryMax` figures are quoted against.
3637
+ * @enum {string}
3638
+ */
3639
+ salaryTimeframe?: "per_year" | "per_month" | "per_week" | "per_day" | "per_hour";
3640
+ /** @description Whether the job appears in featured slots on the public board. */
3641
+ isFeatured?: boolean;
3642
+ /** @description Job expiry as a Unix epoch in milliseconds. On create, omitted or `null` defaults to 30 days from creation. On PATCH, pass `null` to clear an existing expiry. Past timestamps remove the job from the public board. */
3643
+ expiresAt?: number | unknown | unknown;
3644
+ /** @description Time at which the job was first published, as a Unix epoch in milliseconds. When omitted on create with `status: "published"`, the server stamps the current time. Useful for bulk-importing historical jobs while preserving original publication dates. PATCH may overwrite an existing value but cannot clear it. */
3645
+ publishedAt?: number;
3646
+ /** @description Required education credentials. Each value is one of `high_school`, `associate_degree`, `bachelor_degree`, `professional_certificate`, `postgraduate_degree`, or `no_requirements`. */
3647
+ educationRequirements?: ("high_school" | "associate_degree" | "bachelor_degree" | "professional_certificate" | "postgraduate_degree" | "no_requirements")[];
3648
+ /** @description Minimum required experience, expressed in months. */
3649
+ experienceMonths?: number;
3650
+ /** @description If `true`, equivalent experience may substitute for the listed education requirements. */
3651
+ experienceInPlaceOfEducation?: boolean;
3652
+ /**
3653
+ * @description Period denominator for `inOfficeFrequency`.
3654
+ * @enum {string}
3655
+ */
3656
+ inOfficePeriod?: "per_week" | "per_month" | "per_year";
3657
+ /** @description How often the candidate must be in-office over `inOfficePeriod`. */
3658
+ inOfficeFrequency?: number;
3659
+ /** @description Physical office locations associated with the job. Each entry is forward-geocoded server-side; a country mismatch returns `400 jobs_unresolvable_location`. */
3660
+ officeLocations?: components["schemas"]["JobOfficeLocationInput"][];
3661
+ /** @description An external identifier for the job from your own system, such as an ATS requisition ID. Use this value to look up the job later via `GET /v1/jobs?externalId=...` for deduplication. Scoped per-account: two different accounts may reuse the same `externalId` without collision. Up to 255 characters. */
3662
+ externalId?: string;
3663
+ /** @description Board-defined custom-field values, keyed by the field `key` (definitions, including type and option keys, are published at `GET /v1/settings/job-form`). Writes are **additive**: on `PATCH` a key you send is set/overwritten and a key you omit is preserved (unsent keys are never cleared); on `POST` this initializes the bag. Send a key with an intentional-empty value — `null`, `""`, or `[]` — to **clear** it (`""`/`null` clear any type; `[]` clears a `multi_select`); `false` and `0` are kept as real values. Values must match the field type and `single_select`/`multi_select` must use defined option **keys** (not labels); a wrong-typed value is rejected (`custom_field_wrong_type`), never silently cleared. Unknown keys are ignored. The stored bag never contains `null`/empty values. */
3664
+ customFieldValues?: {
3665
+ [key: string]: string | string[] | boolean | number | unknown | unknown;
3666
+ };
3667
+ /** @description The job title. */
3668
+ title?: string;
3669
+ };
3670
+ UpdateLanguagesBody: {
3671
+ languages: {
3672
+ name: string;
3673
+ proficiency: string;
3674
+ }[];
3675
+ };
3676
+ UpdateNotificationPreferenceBody: {
3677
+ /** @enum {string} */
3678
+ channel: "messageEmails" | "applicationEmails";
3679
+ subscribed: boolean;
3680
+ };
3681
+ UpdatePipelineStageBody: {
3682
+ label?: string;
3683
+ hidden?: boolean;
3684
+ };
3685
+ UpdateSkillsBody: {
3686
+ skills: string[];
3687
+ };
3688
+ UpdateTagBody: {
3689
+ /** @description URL-friendly slug for the tag. Auto-generated from `name` when omitted. */
3690
+ slug?: string;
3691
+ /** @description Description for the tag. Sanitized HTML. */
3692
+ description?: string;
3693
+ /**
3694
+ * @description Tag visibility. One of `public` or `internal`.
3695
+ * @enum {string}
3696
+ */
3697
+ visibility?: "public" | "internal";
3698
+ /** @description SEO meta title for the tag page. */
3699
+ metaTitle?: string;
3700
+ /** @description SEO meta description for the tag page. */
3701
+ metaDescription?: string;
3702
+ /** @description The display name of the tag. */
3703
+ name?: string;
3704
+ };
3705
+ Usage: {
3706
+ /** @description Unique identifier for the object. Equal to the account ID — usage is a per-account singleton. */
3707
+ id: string;
3708
+ /**
3709
+ * @description String representing the object's type. Objects of the same type share the same value.
3710
+ * @enum {string}
3711
+ */
3712
+ object: "usage";
3713
+ /** @description Number of jobs currently in `published` status. */
3714
+ activeJobs: number;
3715
+ /** @description Plan-enforced cap on the number of published jobs. */
3716
+ activeJobsLimit: number;
3717
+ /** @description Number of additional jobs the account may publish before hitting the limit. */
3718
+ available: number;
3719
+ /** @description Slug of the account's current plan. */
3720
+ plan: string;
3721
+ };
3722
+ VerifyEmailOtpBody: {
3723
+ code: string;
3724
+ };
3725
+ };
3726
+ responses: never;
3727
+ parameters: never;
3728
+ requestBodies: never;
3729
+ headers: never;
3730
+ pathItems: never;
3731
+ }
3732
+
3733
+ type Schemas = components['schemas'];
3734
+
3735
+ /**
3736
+ * Stripe-shaped success envelopes (`01-conventions.md` §5.1). The
3737
+ * server MAY add top-level fields; consumers MUST ignore unknown
3738
+ * fields.
3739
+ */
3740
+ /**
3741
+ * Medusa-style storefront pagination fields (ADR-0037 §7), populated only by
3742
+ * the board jobs catalog reads (browse / search / company-jobs); absent on
3743
+ * every other list/search. `nextCursor` is preserved alongside (offset-encoded).
3744
+ */
3745
+ interface StorefrontPagination {
3746
+ /** Total matching results ("X jobs"). */
3747
+ count?: number;
3748
+ /** The page size used for this response. */
3749
+ limit?: number;
3750
+ /** Number of items skipped before this page. */
3751
+ offset?: number;
3752
+ /** Items hidden behind the candidate paywall for the current viewer; absent/0 when entitled. */
3753
+ gatedCount?: number;
3754
+ }
3755
+ interface ListEnvelope<T> extends StorefrontPagination {
3756
+ object: 'list';
3757
+ url: string;
3758
+ hasMore: boolean;
3759
+ /** `null` when `hasMore` is false — always present, never undefined. */
3760
+ nextCursor: string | null;
3761
+ data: T[];
3762
+ }
3763
+ interface SearchEnvelope<T> extends StorefrontPagination {
3764
+ object: 'search_result';
3765
+ url: string;
3766
+ hasMore: boolean;
3767
+ nextCursor: string | null;
3768
+ data: T[];
3769
+ }
3770
+
3771
+ type PublicJob = Schemas['PublicJob'];
3772
+ type PublicJobCard = Schemas['PublicJobCard'];
3773
+ /**
3774
+ * A job's opaque, display-only custom-field values (CAV-294), keyed by each
3775
+ * field's `key`. Resolve labels via the board's `CustomFieldDefinition`s
3776
+ * (`board.context().customFields`).
3777
+ */
3778
+ type CustomFieldValues = PublicJob['customFieldValues'];
3779
+ type CustomFieldValue = CustomFieldValues[string];
3780
+ type JobCompany = Schemas['JobCompany'];
3781
+ type OfficeLocation = Schemas['JobOfficeLocation'];
3782
+ type RemoteOption = NonNullable<PublicJob['remoteOption']>;
3783
+ type EmploymentType = NonNullable<PublicJob['employmentType']>;
3784
+ type Seniority = NonNullable<PublicJob['seniority']>;
3785
+ /** Candidate-facing result ordering (ADR-0048); `relevance` is the default. */
3786
+ type JobSort = NonNullable<Schemas['PublicSearchJobsBody']['sort']>;
3787
+ type EducationRequirement = PublicJob['educationRequirements'][number];
3788
+ type RemotePermit = PublicJob['remotePermits'][number];
3789
+ type RemoteTimezone = PublicJob['remoteTimezones'][number];
3790
+ /**
3791
+ * Derived suggestion on a browse list (ADR-0037 §8): jobs surface `category`
3792
+ * and `skill` terms; the companies list surfaces `market` terms.
3793
+ */
3794
+ interface RelatedSearch {
3795
+ type: 'category' | 'skill' | 'market';
3796
+ slug: string;
3797
+ term: string;
3798
+ count: number;
3799
+ }
3800
+ /** The browse list envelope — `PublicJobCard`s + storefront fields + `relatedSearches`. */
3801
+ interface JobCardListEnvelope extends ListEnvelope<PublicJobCard> {
3802
+ relatedSearches?: RelatedSearch[];
3803
+ }
3804
+ /** The search envelope — `PublicJobCard`s + storefront fields. */
3805
+ type JobCardSearchEnvelope = SearchEnvelope<PublicJobCard>;
3806
+ type JobsListQuery = {
3807
+ cursor?: string;
3808
+ /** 1–100. */
3809
+ limit?: number;
3810
+ /** Storefront page offset; takes precedence over `cursor`. `offset + limit` ≤ 10,000. */
3811
+ offset?: number;
3812
+ /** Repeated param (up to 10) — OR-matched. Repeat `companyId` per value. */
3813
+ companyId?: string[];
3814
+ remoteOption?: RemoteOption[];
3815
+ employmentType?: EmploymentType[];
3816
+ seniority?: Seniority[];
3817
+ /** Result ordering (ADR-0048). Absent ⇒ `relevance` (the featured-ranked browse). */
3818
+ sort?: JobSort;
3819
+ /** Place slug for a geo radius search; unresolvable slugs are ignored. */
3820
+ location?: string;
3821
+ /** Radius in km around `location` (10–250; default 50). */
3822
+ radius?: number;
3823
+ /** Category slug seed (the `/jobs/[keyword]` page) — server resolves it to the English source name; unresolvable → 404. */
3824
+ category?: string;
3825
+ /** Skill slug seed (the `/jobs/skills/[skill]` page) — server-resolved; unresolvable → 404. */
3826
+ skill?: string;
3827
+ /** Sparse fieldset (Medusa-style `+field`). Only `'+description'` is supported — adds `description` to each card. */
3828
+ fields?: string;
3829
+ };
3830
+ type JobsSimilarQuery = {
3831
+ /** How many similar jobs to return (1–20; default 5). */
3832
+ limit?: number;
3833
+ };
3834
+ type JobsSearchBody = Schemas['PublicSearchJobsBody'];
3835
+
3836
+ export type { CustomFieldValue as C, EmploymentType as E, JobsListQuery as J, ListEnvelope as L, OfficeLocation as O, PublicJob as P, RemoteOption as R, Schemas as S, Seniority as a, RelatedSearch as b, components as c, JobCardListEnvelope as d, JobsSearchBody as e, JobCardSearchEnvelope as f, JobsSimilarQuery as g, SearchEnvelope as h, CustomFieldValues as i, EducationRequirement as j, JobCompany as k, JobSort as l, PublicJobCard as m, RemotePermit as n, RemoteTimezone as o, StorefrontPagination as p };