@cavuno/board 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,3 +1,1870 @@
1
+ interface components {
2
+ schemas: {
3
+ /** @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. */
4
+ AdminOnlyResourceLinks: {
5
+ /**
6
+ * Format: uri
7
+ * @description URL inside the Cavuno app where the authenticated owner can manage this resource.
8
+ */
9
+ admin: string;
10
+ };
11
+ ApiKey: {
12
+ /** @description Unique identifier for the object. */
13
+ id: string;
14
+ /**
15
+ * @description String representing the object's type. Objects of the same type share the same value.
16
+ * @enum {string}
17
+ */
18
+ object: "api_key";
19
+ /** @description Public key ID component, embedded in the key prefix as `cavuno_live_<keyId>_`. */
20
+ keyId: string;
21
+ /** @description Human-readable name for the key, shown in the dashboard. */
22
+ name: string;
23
+ /** @description Public prefix in the form `cavuno_live_<keyId>_`. Safe to log; the full plaintext secret is never returned by the API. */
24
+ prefix: string;
25
+ /** @description Time at which the key was created. Unix epoch in milliseconds. */
26
+ createdAt: number;
27
+ /** @description Identifier of the user who minted the key. */
28
+ createdBy: string;
29
+ /** @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. */
30
+ lastUsedAt: number | null;
31
+ /** @description Time at which the key was revoked, or `null` if the key is still active. Unix epoch in milliseconds. */
32
+ revokedAt: number | null;
33
+ /** @description Time at which the key expires, or `null` if the key has no expiry. Unix epoch in milliseconds. */
34
+ expiresAt: number | null;
35
+ };
36
+ AuditLogEntry: {
37
+ /** @description Unique identifier for the object. */
38
+ id: string;
39
+ /**
40
+ * @description String representing the object's type. Objects of the same type share the same value.
41
+ * @enum {string}
42
+ */
43
+ object: "audit_log";
44
+ /** @description Identifier of the account the entry belongs to. */
45
+ accountId: string;
46
+ /**
47
+ * @description Type of actor that performed the action.
48
+ * @enum {string}
49
+ */
50
+ actorType: "api_key" | "oauth_token" | "user_session" | "system";
51
+ /** @description Identifier of the actor that performed the action. */
52
+ actorId: string;
53
+ /** @description Human-readable label for the actor, suitable for display. */
54
+ actorLabel: string;
55
+ /** @description Action that was performed (e.g. `jobs.create`, `companies.update`). */
56
+ action: string;
57
+ /** @description Type of resource the action was performed on. */
58
+ resourceType: string;
59
+ /** @description Identifier of the resource the action was performed on, or `null` for resource-less actions. */
60
+ resourceId: string | null;
61
+ /** @description Serialized JSON snapshot of the resource before the action, or `null` for create actions. */
62
+ before: string | null;
63
+ /** @description Serialized JSON snapshot of the resource after the action, or `null` for delete actions. */
64
+ after: string | null;
65
+ /** @description Serialized JSON of free-form metadata about the action (e.g. truncation byte sizes), or `null` if none was attached. */
66
+ metadata: string | null;
67
+ /** @description IP address the request originated from, or `null` if unavailable. */
68
+ ipAddress: string | null;
69
+ /** @description User-agent string from the request, or `null` if unavailable. */
70
+ userAgent: string | null;
71
+ /** @description Identifier of the request that produced the entry. Use this to correlate with platform logs. */
72
+ requestId: string;
73
+ /** @description Time at which the audit entry was written. Unix epoch in milliseconds. */
74
+ timestamp: number;
75
+ };
76
+ BatchRequestBody: {
77
+ /** @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. */
78
+ operations: ({
79
+ id: string;
80
+ /** @enum {string} */
81
+ method: "POST";
82
+ body?: unknown;
83
+ action?: string;
84
+ resourceId?: string;
85
+ } | {
86
+ id: string;
87
+ /** @enum {string} */
88
+ method: "PATCH";
89
+ body?: unknown;
90
+ resourceId: string;
91
+ } | {
92
+ id: string;
93
+ /** @enum {string} */
94
+ method: "DELETE";
95
+ resourceId: string;
96
+ })[];
97
+ };
98
+ BlogAuthor: {
99
+ /** @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}`). */
100
+ id: string;
101
+ /**
102
+ * @description String representing the object's type. Objects of the same type share the same value.
103
+ * @enum {string}
104
+ */
105
+ object: "blog_author";
106
+ /** @description Display name of the author. */
107
+ name: string;
108
+ /** @description URL-friendly slug for the author. */
109
+ slug: string;
110
+ /** @description Short biography, or `null` if not set. */
111
+ bio: string | null;
112
+ /** @description The author's email address, or `null` if not set. */
113
+ email: string | null;
114
+ /** @description Author visibility status, or `null` if not set. */
115
+ status: string | null;
116
+ /** @description URL of the author avatar, or `null` if no avatar is set. */
117
+ avatarUrl: string | null;
118
+ /** @description The author's website URL, or `null` if not set. */
119
+ websiteUrl: string | null;
120
+ /** @description The author's X (Twitter) URL, or `null` if not set. */
121
+ twitterUrl: string | null;
122
+ /** @description The author's LinkedIn URL, or `null` if not set. */
123
+ linkedinUrl: string | null;
124
+ /** @description The author's GitHub URL, or `null` if not set. */
125
+ githubUrl: string | null;
126
+ /** @description SEO meta title, or `null` if not set. */
127
+ metaTitle: string | null;
128
+ /** @description SEO meta description, or `null` if not set. */
129
+ metaDescription: string | null;
130
+ /** @description Time at which the author was created. ISO 8601 datetime. */
131
+ createdAt: string;
132
+ /** @description Time at which the author was last updated, or `null` if it has never been updated. ISO 8601 datetime. */
133
+ updatedAt: string | null;
134
+ };
135
+ BlogPost: components["schemas"]["BlogPostSummary"] & {
136
+ html: string | null;
137
+ };
138
+ BlogPostSummary: {
139
+ /** @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}`). */
140
+ id: string;
141
+ /** @enum {string} */
142
+ object: "blog_post";
143
+ title: string;
144
+ slug: string;
145
+ status: string;
146
+ visibility: string;
147
+ type: string;
148
+ featured: boolean;
149
+ authorIds: string[];
150
+ tagIds: string[];
151
+ coverUrl: string | null;
152
+ ogImageUrl: string | null;
153
+ featureImageAlt: string | null;
154
+ featureImageCaption: string | null;
155
+ customExcerpt: string | null;
156
+ readingTimeMin: number | null;
157
+ seoTitle: string | null;
158
+ seoDescription: string | null;
159
+ canonicalUrl: string | null;
160
+ publishedAt: string | null;
161
+ createdAt: string;
162
+ updatedAt: string | null;
163
+ };
164
+ BlogPostsBatchRequest: {
165
+ /** @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. */
166
+ operations: ({
167
+ id: string;
168
+ /** @enum {string} */
169
+ method: "POST";
170
+ body?: unknown;
171
+ action?: string;
172
+ resourceId?: string;
173
+ } | {
174
+ id: string;
175
+ /** @enum {string} */
176
+ method: "PATCH";
177
+ body?: unknown;
178
+ resourceId: string;
179
+ } | {
180
+ id: string;
181
+ /** @enum {string} */
182
+ method: "DELETE";
183
+ resourceId: string;
184
+ })[];
185
+ };
186
+ BlogTag: {
187
+ /** @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}`). */
188
+ id: string;
189
+ /**
190
+ * @description String representing the object's type. Objects of the same type share the same value.
191
+ * @enum {string}
192
+ */
193
+ object: "blog_tag";
194
+ /** @description Display name of the tag. */
195
+ name: string;
196
+ /** @description URL-friendly slug for the tag. */
197
+ slug: string;
198
+ /** @description Tag description, or `null` if not set. */
199
+ description: string | null;
200
+ /** @description Tag visibility, or `null` if not set. */
201
+ visibility: string | null;
202
+ /** @description SEO meta title, or `null` if not set. */
203
+ metaTitle: string | null;
204
+ /** @description SEO meta description, or `null` if not set. */
205
+ metaDescription: string | null;
206
+ /** @description Time at which the tag was created. ISO 8601 datetime. */
207
+ createdAt: string;
208
+ /** @description Time at which the tag was last updated, or `null` if it has never been updated. ISO 8601 datetime. */
209
+ updatedAt: string | null;
210
+ };
211
+ BoardAccessGrant: {
212
+ /** @enum {string} */
213
+ object: "board_access_grant";
214
+ /** @description The board-access grant. Send it as the `X-Board-Access` header on subsequent content reads to pass the password wall. */
215
+ token: string;
216
+ };
217
+ BoardAuthForgotPasswordBody: {
218
+ /** Format: email */
219
+ email: string;
220
+ };
221
+ BoardAuthLoginBody: {
222
+ /** Format: email */
223
+ email: string;
224
+ password: string;
225
+ };
226
+ BoardAuthLogoutBody: {
227
+ refreshToken: string;
228
+ };
229
+ BoardAuthRefreshBody: {
230
+ refreshToken: string;
231
+ };
232
+ BoardAuthRegisterBody: {
233
+ /**
234
+ * @description Which role profile to create on the board.
235
+ * @enum {string}
236
+ */
237
+ role: "candidate" | "employer";
238
+ /**
239
+ * @description Registration method. Only `emailpass` is supported.
240
+ * @enum {string}
241
+ */
242
+ method: "emailpass";
243
+ /** Format: email */
244
+ email: string;
245
+ /** @description Minimum 8 characters. */
246
+ password: string;
247
+ displayName: string;
248
+ };
249
+ BoardAuthResetPasswordBody: {
250
+ token: string;
251
+ /** @description Minimum 8 characters. */
252
+ password: string;
253
+ };
254
+ BoardAuthSession: {
255
+ /** @enum {string} */
256
+ object: "board_auth_session";
257
+ /** @description Short-lived JWT (1 hour). Send as `Authorization: Bearer`. */
258
+ accessToken: string;
259
+ /** @description Opaque single-use refresh token (30 days). Each refresh returns a replacement; a reused token is rejected. */
260
+ refreshToken: string;
261
+ /** @description Access-token expiry, epoch milliseconds. */
262
+ expiresAt: number;
263
+ boardUser: components["schemas"]["BoardUser"];
264
+ };
265
+ BoardAuthVerifyEmailBody: {
266
+ token: string;
267
+ };
268
+ BoardSeo: {
269
+ /** @enum {string} */
270
+ object: "board_seo";
271
+ /** @description Verbatim `ads.txt` content, or `null` when not configured. */
272
+ adsTxt: string | null;
273
+ /** @description IndexNow key-file content, or `null` when not configured. */
274
+ indexNowKey: string | null;
275
+ /** @description Google site-verification token for the `<meta>` tag, or `null`. */
276
+ googleSiteVerification: string | null;
277
+ /**
278
+ * Format: uri
279
+ * @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.
280
+ */
281
+ canonicalBase: string;
282
+ /** @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. */
283
+ icons: {
284
+ ico: string | null;
285
+ svg: string | null;
286
+ appleTouch: string | null;
287
+ icon192: string | null;
288
+ icon512: string | null;
289
+ iconMaskable512: string | null;
290
+ };
291
+ /** @description Web-manifest metadata; assemble `site.webmanifest` from this + `icons`. */
292
+ manifest: {
293
+ name: string;
294
+ themeColor: string;
295
+ };
296
+ };
297
+ BoardUser: {
298
+ /** @description Board user ID. */
299
+ id: string;
300
+ /** @enum {string} */
301
+ object: "board_user";
302
+ /** @enum {string} */
303
+ role: "candidate" | "employer";
304
+ email: string;
305
+ displayName: string | null;
306
+ emailVerified: boolean;
307
+ };
308
+ CompaniesBatchRequest: {
309
+ /** @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. */
310
+ operations: ({
311
+ id: string;
312
+ /** @enum {string} */
313
+ method: "POST";
314
+ body?: unknown;
315
+ action?: string;
316
+ resourceId?: string;
317
+ } | {
318
+ id: string;
319
+ /** @enum {string} */
320
+ method: "PATCH";
321
+ body?: unknown;
322
+ resourceId: string;
323
+ } | {
324
+ id: string;
325
+ /** @enum {string} */
326
+ method: "DELETE";
327
+ resourceId: string;
328
+ })[];
329
+ };
330
+ Company: components["schemas"]["CompanySummary"] & {
331
+ /** @description Long-form description of the company, or `null` if not set. */
332
+ description: string | null;
333
+ /** @description Whether automated backfill of jobs from this company is supported, or `null` if not yet evaluated. */
334
+ canBackfill: boolean | null;
335
+ /** @description Total number of jobs at this company across all statuses. */
336
+ jobCount: number;
337
+ /** @description Number of currently-published jobs at this company. */
338
+ publishedJobCount: number;
339
+ };
340
+ CompanyMarket: {
341
+ /** @enum {string} */
342
+ object: "company_market";
343
+ slug: string;
344
+ name: string;
345
+ /** @description Number of companies on the board in this market. */
346
+ companyCount: number;
347
+ };
348
+ CompanyPublic: {
349
+ /** @description Unique identifier for the object. Use this value as the `{id}` path parameter for the company endpoints (e.g. `GET /v1/companies/{id}`). */
350
+ id: string;
351
+ /**
352
+ * @description String representing the object's type. Objects of the same type share the same value.
353
+ * @enum {string}
354
+ */
355
+ object: "public_company";
356
+ /** @description Display name of the company. */
357
+ name: string;
358
+ /** @description URL-friendly slug for the company. */
359
+ slug: string;
360
+ /** @description Public company website URL, or `null` if not set. */
361
+ website: string | null;
362
+ /** @description URL of the company logo, or `null` if no logo is set. */
363
+ logoUrl: string | null;
364
+ /** @description Long-form description of the company, or `null` if not set. */
365
+ description: string | null;
366
+ /** @description Total number of public-facing jobs at this company. Currently mirrors `publishedJobCount`. */
367
+ jobCount: number;
368
+ /** @description Number of currently-published, non-expired jobs at this company. */
369
+ publishedJobCount: number;
370
+ links: components["schemas"]["PublicCompanyLinks"];
371
+ };
372
+ CompanySummary: {
373
+ /** @description Unique identifier for the object. Use this value as the `{id}` path parameter for the company endpoints (e.g. `GET /v1/companies/{id}`). */
374
+ id: string;
375
+ /**
376
+ * @description String representing the object's type. Objects of the same type share the same value.
377
+ * @enum {string}
378
+ */
379
+ object: "company";
380
+ /** @description Display name of the company. */
381
+ name: string;
382
+ /** @description URL-friendly slug for the company. */
383
+ slug: string;
384
+ /** @description Public company website URL, or `null` if not set. */
385
+ website: string | null;
386
+ /** @description URL of the company logo, or `null` if no logo is set. */
387
+ logoUrl: string | null;
388
+ /** @description One-line summary of the company, or `null` if not set. */
389
+ summary: string | null;
390
+ /** @description X (Twitter) profile URL, or `null` if not set. */
391
+ xUrl: string | null;
392
+ /** @description LinkedIn page URL, or `null` if not set. */
393
+ linkedinUrl: string | null;
394
+ /** @description Facebook page URL, or `null` if not set. */
395
+ facebookUrl: string | null;
396
+ /** @description Time at which the company was created. ISO 8601 datetime. */
397
+ createdAt: string;
398
+ /** @description Time at which the company was last updated, or `null` if it has never been updated. ISO 8601 datetime. */
399
+ updatedAt: string | null;
400
+ /** @description Public + admin URLs for this company. `public` may be `null` if the company lacks a slug. */
401
+ links: components["schemas"]["ResourceLinks"] & {
402
+ /**
403
+ * Format: uri
404
+ * @description Canonical public URL for this company on the board, or `null` when no slug is set.
405
+ */
406
+ public?: string | null;
407
+ };
408
+ };
409
+ CreateAuthorBody: {
410
+ /** @description URL-friendly slug for the author. Auto-generated from `name` when omitted. */
411
+ slug?: string;
412
+ /** @description Short biography for the author. Sanitized HTML. */
413
+ bio?: string;
414
+ /**
415
+ * Format: email
416
+ * @description The author's email address.
417
+ */
418
+ email?: string;
419
+ /**
420
+ * @description Author visibility status. One of `active` or `inactive`.
421
+ * @enum {string}
422
+ */
423
+ status?: "active" | "inactive";
424
+ /** @description Storage ID of an uploaded avatar image (from `POST /v1/media/upload`). Pass `null` to clear an existing avatar. */
425
+ avatarStorageId?: string | null;
426
+ /** @description The author's personal website URL. Normalized to a canonical URL when stored. */
427
+ websiteUrl?: string;
428
+ /** @description The author's X (Twitter) profile URL. Stored as the canonical `https://x.com/<handle>` URL. */
429
+ twitterUrl?: string;
430
+ /** @description The author's LinkedIn profile URL. */
431
+ linkedinUrl?: string;
432
+ /** @description The author's GitHub profile URL. */
433
+ githubUrl?: string;
434
+ /** @description SEO meta title for the author page. */
435
+ metaTitle?: string;
436
+ /** @description SEO meta description for the author page. */
437
+ metaDescription?: string;
438
+ /** @description The author's display name. */
439
+ name: string;
440
+ };
441
+ CreateBlogPostBody: {
442
+ slug?: string;
443
+ html?: string;
444
+ customExcerpt?: string;
445
+ readingTimeMin?: number;
446
+ featured?: boolean;
447
+ authorIds?: string[];
448
+ tagIds?: string[];
449
+ coverStorageId?: string | null;
450
+ ogImageStorageId?: string | null;
451
+ featureImageAlt?: string;
452
+ featureImageCaption?: string;
453
+ seoTitle?: string;
454
+ seoDescription?: string;
455
+ /** Format: uri */
456
+ canonicalUrl?: string;
457
+ /** Format: date-time */
458
+ publishedAt?: string;
459
+ title: string;
460
+ /** @enum {string} */
461
+ status?: "draft" | "scheduled" | "published";
462
+ };
463
+ CreateCompanyBody: {
464
+ /** @description Public company website URL. Normalized to a canonical apex domain when stored. */
465
+ website?: string;
466
+ /** @description One-line summary of the company. Up to 280 characters. */
467
+ summary?: string;
468
+ /** @description Long-form description of the company. Up to 25,000 characters. */
469
+ description?: string;
470
+ /** @description X (Twitter) profile URL or handle. Stored as the canonical handle. */
471
+ xUrl?: string;
472
+ /** @description LinkedIn company page URL. */
473
+ linkedinUrl?: string;
474
+ /** @description Facebook company page URL. */
475
+ facebookUrl?: string;
476
+ /** @description The company's display name. */
477
+ name: string;
478
+ /** @description URL-friendly slug for the company. Auto-generated from `name` when omitted. */
479
+ slug?: string;
480
+ };
481
+ CreateJobBody: {
482
+ /** @description The ID of an existing company. Provide either `companyId` or `company`, not both. */
483
+ companyId?: string;
484
+ /** @description Long-form description of the role. Up to 25,000 characters. */
485
+ description: string;
486
+ /** @description URL-friendly slug for the job. Auto-generated from `title` when omitted. */
487
+ slug?: string;
488
+ /**
489
+ * @description Employment type of the role.
490
+ * @enum {string}
491
+ */
492
+ employmentType?: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other";
493
+ /**
494
+ * @description Whether the role is on-site, hybrid, or fully remote.
495
+ * @enum {string}
496
+ */
497
+ remoteOption?: "on_site" | "hybrid" | "remote";
498
+ /** @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. */
499
+ remotePermits?: {
500
+ /** @enum {string} */
501
+ type: "worldwide" | "world_region" | "continent" | "region" | "subregion" | "subdivision" | "country" | "custom";
502
+ value: string;
503
+ }[];
504
+ /** @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. */
505
+ remoteTimezones?: {
506
+ /** @enum {string} */
507
+ type: "all" | "world_region" | "continent" | "region" | "subregion" | "country" | "timezone";
508
+ value: string;
509
+ plusMinus?: number;
510
+ }[];
511
+ /**
512
+ * @description Whether the employer sponsors visas for remote candidates. One of `yes`, `no`, or `unknown`.
513
+ * @enum {string}
514
+ */
515
+ remoteSponsorship?: "yes" | "no" | "unknown";
516
+ /**
517
+ * @description Seniority level of the role.
518
+ * @enum {string}
519
+ */
520
+ seniority?: "entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive";
521
+ /** @description Where candidates apply. Accepts an HTTPS URL, a `mailto:` URI, or a bare email address (which is normalized to `mailto:` form). */
522
+ applicationUrl: string;
523
+ /** @description Minimum salary, in `salaryCurrency` units. */
524
+ salaryMin?: number;
525
+ /** @description Maximum salary, in `salaryCurrency` units. */
526
+ salaryMax?: number;
527
+ /** @description Three-letter ISO 4217 currency code for `salaryMin` and `salaryMax`. */
528
+ salaryCurrency?: string;
529
+ /**
530
+ * @description Period the `salaryMin` and `salaryMax` figures are quoted against.
531
+ * @enum {string}
532
+ */
533
+ salaryTimeframe?: "per_year" | "per_month" | "per_week" | "per_day" | "per_hour";
534
+ /** @description Whether the job appears in featured slots on the public board. */
535
+ isFeatured?: boolean;
536
+ /** @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. */
537
+ expiresAt?: number | unknown | unknown;
538
+ /** @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. */
539
+ publishedAt?: number;
540
+ /** @description Required education credentials. Each value is one of `high_school`, `associate_degree`, `bachelor_degree`, `professional_certificate`, `postgraduate_degree`, or `no_requirements`. */
541
+ educationRequirements?: ("high_school" | "associate_degree" | "bachelor_degree" | "professional_certificate" | "postgraduate_degree" | "no_requirements")[];
542
+ /** @description Minimum required experience, expressed in months. */
543
+ experienceMonths?: number;
544
+ /** @description If `true`, equivalent experience may substitute for the listed education requirements. */
545
+ experienceInPlaceOfEducation?: boolean;
546
+ /**
547
+ * @description Period denominator for `inOfficeFrequency`.
548
+ * @enum {string}
549
+ */
550
+ inOfficePeriod?: "per_week" | "per_month" | "per_year";
551
+ /** @description How often the candidate must be in-office over `inOfficePeriod`. */
552
+ inOfficeFrequency?: number;
553
+ /** @description Physical office locations associated with the job. Each entry is forward-geocoded server-side; a country mismatch returns `400 jobs_unresolvable_location`. */
554
+ officeLocations?: components["schemas"]["JobOfficeLocationInput"][];
555
+ /** @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. */
556
+ externalId?: string;
557
+ /** @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. */
558
+ customFieldValues?: {
559
+ [key: string]: string | string[] | boolean | number | unknown | unknown;
560
+ };
561
+ /** @description The job title. */
562
+ title: string;
563
+ company?: components["schemas"]["InlineCompanyInput"];
564
+ /**
565
+ * @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.
566
+ * @enum {string}
567
+ */
568
+ status?: "draft" | "published";
569
+ };
570
+ CreateTagBody: {
571
+ /** @description URL-friendly slug for the tag. Auto-generated from `name` when omitted. */
572
+ slug?: string;
573
+ /** @description Description for the tag. Sanitized HTML. */
574
+ description?: string;
575
+ /**
576
+ * @description Tag visibility. One of `public` or `internal`.
577
+ * @enum {string}
578
+ */
579
+ visibility?: "public" | "internal";
580
+ /** @description SEO meta title for the tag page. */
581
+ metaTitle?: string;
582
+ /** @description SEO meta description for the tag page. */
583
+ metaDescription?: string;
584
+ /** @description The display name of the tag. */
585
+ name: string;
586
+ };
587
+ CustomFieldDefinition: {
588
+ /** @description Immutable per-board slug. Use this as the key in `customFieldValues` when writing values via POST/PATCH /v1/jobs. */
589
+ key: string;
590
+ /** @description Authoring-default label; the localized public string lives in the board template. */
591
+ label: string;
592
+ /**
593
+ * @description Field type, which dictates the accepted value: `short_text`/`long_text` → string; `single_select` → one option key (string); `multi_select` → array of option keys; `boolean` → boolean; `number` → number.
594
+ * @enum {string}
595
+ */
596
+ type: "short_text" | "long_text" | "single_select" | "multi_select" | "boolean" | "number";
597
+ /** @description Present only for `single_select`/`multi_select`. A written value must be one (or, for multi, several) of these option `key`s — never a label. */
598
+ options?: components["schemas"]["CustomFieldOption"][];
599
+ /** @description When true, the value cannot be cleared or left empty on a write (rejected with `custom_field_required`). */
600
+ required: boolean;
601
+ /** @description Inclusive minimum for `number` fields, when set. */
602
+ min?: number;
603
+ /** @description Inclusive maximum for `number` fields, when set. */
604
+ max?: number;
605
+ };
606
+ CustomFieldOption: {
607
+ /** @description Stable option key — send this in a write, not the label. */
608
+ key: string;
609
+ /** @description Display label (authoring default; localized per board in the template). */
610
+ label: string;
611
+ };
612
+ DuplicateJobBody: Record<string, never>;
613
+ DynamicClientRegistrationRequest: {
614
+ /** @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. */
615
+ redirect_uris: string[];
616
+ /** @description Human-readable client name shown to users on the consent screen. Recommended for MCP clients; defaults to "MCP client" when omitted. */
617
+ client_name?: string;
618
+ /** @description Space-separated list of scopes the client may request. When omitted, the client is registered for all scopes. */
619
+ scope?: string;
620
+ /**
621
+ * @description OAuth token endpoint authentication method. Use `none` for public PKCE clients that cannot keep a client secret.
622
+ * @enum {string}
623
+ */
624
+ token_endpoint_auth_method?: "client_secret_basic" | "none";
625
+ };
626
+ DynamicClientRegistrationResponse: {
627
+ /** @description Public OAuth client identifier. */
628
+ client_id: string;
629
+ /** @description Time at which the client was registered. Unix epoch in seconds. */
630
+ client_id_issued_at: number;
631
+ /** @description Plaintext OAuth client secret. Returned exactly once for confidential clients; omitted for public clients. */
632
+ client_secret?: string;
633
+ /** @description Time at which the client secret expires. Unix epoch in seconds, or `0` if the secret does not expire. Omitted for public clients. */
634
+ client_secret_expires_at?: number;
635
+ /** @description Array of redirect URIs registered for the client. */
636
+ redirect_uris: string[];
637
+ /** @description Human-readable client name shown to users on the consent screen. */
638
+ client_name: string;
639
+ /** @description OAuth grant types the client is permitted to use. */
640
+ grant_types: string[];
641
+ /** @description OAuth response types the client is permitted to use. */
642
+ response_types: string[];
643
+ /** @description Authentication method the client uses at the token endpoint. */
644
+ token_endpoint_auth_method: string;
645
+ /** @description Space-separated list of scopes the client may request. */
646
+ scope: string;
647
+ };
648
+ FindOrCreateCompanyBody: {
649
+ /** @description The company's display name. */
650
+ name: string;
651
+ /** @description Public company website URL. Used to resolve to an existing company by domain before falling back to creation. */
652
+ website?: string;
653
+ /** @description One-line summary of the company. Up to 280 characters. */
654
+ summary?: string;
655
+ /** @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. */
656
+ matchByName?: boolean;
657
+ /** @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. */
658
+ createIfMissing?: boolean;
659
+ };
660
+ /** @description An inline company payload, resolved via `find-or-create` before the job is created. Provide either `company` or `companyId`, not both. */
661
+ InlineCompanyInput: {
662
+ /** @description The company's display name. */
663
+ name: string;
664
+ /** @description Public company website URL. Used to resolve to an existing company by domain before falling back to creation. */
665
+ website?: string;
666
+ /** @description One-line summary of the company. Up to 280 characters. */
667
+ summary?: string;
668
+ /** @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. */
669
+ matchByName?: boolean;
670
+ /** @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. */
671
+ createIfMissing?: boolean;
672
+ };
673
+ Job: components["schemas"]["JobSummary"] & {
674
+ /** @description Public + admin URLs for this job. `public` may be `null` if the job lacks a slug or company-slug. */
675
+ links?: components["schemas"]["ResourceLinks"] & {
676
+ /**
677
+ * Format: uri
678
+ * @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).
679
+ */
680
+ public?: string | null;
681
+ };
682
+ /** @description Long-form description of the role, or `null` if not specified. */
683
+ description: string | null;
684
+ /** @description Where candidates apply, or `null` if not specified. An HTTPS URL or `mailto:` URI. */
685
+ applicationUrl: string | null;
686
+ /** @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. */
687
+ remotePermits: {
688
+ type: string;
689
+ value: string;
690
+ }[];
691
+ /** @description Read-only — derived from `remotePermits`. `true` only when the authored selection is a single `{type:"worldwide"}` entry. */
692
+ remoteWorldwide: boolean | null;
693
+ /** @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. */
694
+ remoteTimezones: {
695
+ type: string;
696
+ value: string;
697
+ plusMinus?: number;
698
+ }[];
699
+ /** @description Read-only — derived from `remoteTimezones` (per-country/per-region offset fan-out). UTC hour offsets used by the job-search index. */
700
+ remoteAllowedTzOffsets: number[];
701
+ /** @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. */
702
+ remoteWorkPermitCountryCodes: string[];
703
+ /** @description Read-only — derived from `remotePermits` (subdivision entries only). ISO 3166-2 codes. */
704
+ remoteWorkPermitSubdivisionCodes: string[];
705
+ /**
706
+ * @description Whether the employer sponsors visas for remote candidates. One of `yes`, `no`, or `unknown`.
707
+ * @enum {string}
708
+ */
709
+ remoteSponsorship: "yes" | "no" | "unknown";
710
+ /** @description Required education credentials. Each value is one of `high_school`, `associate_degree`, `bachelor_degree`, `professional_certificate`, `postgraduate_degree`, or `no_requirements`. */
711
+ educationRequirements: ("high_school" | "associate_degree" | "bachelor_degree" | "professional_certificate" | "postgraduate_degree" | "no_requirements")[];
712
+ /** @description Minimum required experience in months, or `null` if not specified. */
713
+ experienceMonths: number | null;
714
+ /** @description If `true`, equivalent experience may substitute for the listed education requirements. `null` if not specified. */
715
+ experienceInPlaceOfEducation: boolean | null;
716
+ /**
717
+ * @description Period denominator for `inOfficeFrequency`, or `null` if not specified.
718
+ * @enum {string|null}
719
+ */
720
+ inOfficePeriod: "per_week" | "per_month" | "per_year" | null;
721
+ /** @description How often the candidate must be in-office over `inOfficePeriod`, or `null` if not specified. */
722
+ inOfficeFrequency: number | null;
723
+ company: components["schemas"]["JobCompany"];
724
+ /** @description Physical office locations associated with the job. */
725
+ officeLocations: components["schemas"]["JobOfficeLocation"][];
726
+ };
727
+ /** @description Embedded company resource for the job, or `null` if no company is attached. */
728
+ JobCompany: {
729
+ /** @description Unique identifier for the company. */
730
+ id: string;
731
+ /** @description Display name of the company, or `null` if not yet set. */
732
+ name: string | null;
733
+ /** @description URL slug of the company, or `null` if not yet set. */
734
+ slug: string | null;
735
+ /** @description URL of the company logo, or `null` if no logo is set. */
736
+ logoUrl: string | null;
737
+ /** @description Company website URL, or `null` if no website is set. */
738
+ website: string | null;
739
+ } | null;
740
+ JobFormConfig: {
741
+ sponsorship?: {
742
+ visible: boolean;
743
+ };
744
+ salary?: {
745
+ visible: boolean;
746
+ required?: boolean;
747
+ minBound?: number;
748
+ maxBound?: number;
749
+ allowedCurrencies?: string[];
750
+ };
751
+ seniority?: {
752
+ visible: boolean;
753
+ required?: boolean;
754
+ allowedOptions?: string[];
755
+ };
756
+ workArrangement?: {
757
+ allowedOptions: string[];
758
+ };
759
+ employmentType?: {
760
+ allowedOptions: string[];
761
+ };
762
+ location?: {
763
+ visible: boolean;
764
+ allowedCountries?: string[];
765
+ };
766
+ /** @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. */
767
+ customFields?: components["schemas"]["CustomFieldDefinition"][];
768
+ };
769
+ JobOfficeLocation: {
770
+ /** @description ISO 3166-1 alpha-2 country code, or `null` if the location was not resolved. */
771
+ countryCode: string | null;
772
+ /** @description Full country name, or `null` if the location was not resolved. */
773
+ country: string | null;
774
+ /** @description Neighborhood or sub-locality, or `null` if not resolved. */
775
+ locality: string | null;
776
+ /** @description City, or `null` if not resolved. */
777
+ city: string | null;
778
+ /** @description Region, state, or province name, or `null` if not resolved. */
779
+ region: string | null;
780
+ /** @description Region or state code (e.g. `CA` for California), or `null` if not resolved. */
781
+ regionCode: string | null;
782
+ /** @description Postal or ZIP code, or `null` if not resolved. */
783
+ postalCode: string | null;
784
+ /** @description Pre-formatted display name for the location, or `null` if not resolved. */
785
+ displayName: string | null;
786
+ };
787
+ JobOfficeLocationInput: {
788
+ /** @description Neighborhood or sub-locality. */
789
+ locality?: string;
790
+ /** @description City. */
791
+ city: string;
792
+ /** @description Region, state, or province. */
793
+ region?: string;
794
+ /** @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`). */
795
+ country: string;
796
+ } | {
797
+ /** @description Free-form location string (e.g. `"Berlin, Germany"`, `"Mountain View, California, USA"`). Mapbox parses + ranks candidates server-side; rejects on low confidence. */
798
+ query: string;
799
+ };
800
+ JobSummary: {
801
+ /** @description Unique identifier for the object. Use this value as the `{id}` path parameter for the job endpoints (e.g. `GET /v1/jobs/{id}`). */
802
+ id: string;
803
+ /**
804
+ * @description String representing the object's type. Objects of the same type share the same value.
805
+ * @enum {string}
806
+ */
807
+ object: "job";
808
+ /** @description The job title. */
809
+ title: string;
810
+ /** @description URL-friendly slug used in public board URLs, or `null` if no slug is set. */
811
+ slug: string | null;
812
+ /**
813
+ * @description Current status of the job. One of `draft`, `published`, `expired`, or `archived`.
814
+ * @enum {string}
815
+ */
816
+ status: "draft" | "published" | "expired" | "archived";
817
+ /** @description Identifier of the company the job belongs to, or `null` if no company is attached. */
818
+ companyId: string | null;
819
+ /**
820
+ * @description Employment type of the role, or `null` if not specified.
821
+ * @enum {string|null}
822
+ */
823
+ employmentType: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other" | null;
824
+ /**
825
+ * @description Whether the role is on-site, hybrid, or fully remote, or `null` if not specified.
826
+ * @enum {string|null}
827
+ */
828
+ remoteOption: "on_site" | "hybrid" | "remote" | null;
829
+ /**
830
+ * @description Seniority level of the role, or `null` if not specified.
831
+ * @enum {string|null}
832
+ */
833
+ seniority: "entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive" | null;
834
+ /** @description Minimum salary in `salaryCurrency` units, or `null` if not specified. */
835
+ salaryMin: number | null;
836
+ /** @description Maximum salary in `salaryCurrency` units, or `null` if not specified. */
837
+ salaryMax: number | null;
838
+ /** @description Three-letter ISO 4217 currency code for the salary range, or `null` if no salary is specified. */
839
+ salaryCurrency: string | null;
840
+ /**
841
+ * @description Period the salary range is quoted against, or `null` if no salary is specified.
842
+ * @enum {string|null}
843
+ */
844
+ salaryTimeframe: "per_year" | "per_month" | "per_week" | "per_day" | "per_hour" | null;
845
+ /** @description Whether the job appears in featured slots on the public board. */
846
+ isFeatured: boolean;
847
+ /** @description Time at which the job was first published, or `null` if not yet published. ISO 8601 datetime. */
848
+ publishedAt: string | null;
849
+ /** @description Time at which the job expires, or `null` if no expiry is set. ISO 8601 datetime. */
850
+ expiresAt: string | null;
851
+ /** @description Time at which the job was created. ISO 8601 datetime. */
852
+ createdAt: string;
853
+ /** @description Time at which the job was last updated. ISO 8601 datetime. */
854
+ updatedAt: string;
855
+ /** @description External identifier supplied by the caller on create, used for deduplication via `GET /v1/jobs?externalId=...`. `null` when no external identifier was set. */
856
+ externalId: string | null;
857
+ /** @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. */
858
+ customFieldValues: {
859
+ [key: string]: string | string[] | boolean | number;
860
+ };
861
+ links: components["schemas"]["AdminOnlyResourceLinks"];
862
+ };
863
+ MediaGet: components["schemas"]["MediaUpload"] & {
864
+ /** @description Time at which the file was uploaded. ISO 8601 datetime. */
865
+ uploadedAt: string;
866
+ /** @description Resources currently referencing this file. Currently always `[]` — the resolver is not yet implemented. */
867
+ referencedBy: {
868
+ /** @description Type of the resource referencing this file. */
869
+ resourceType: string;
870
+ /** @description Identifier of the resource referencing this file. */
871
+ resourceId: string;
872
+ }[];
873
+ };
874
+ MediaUpload: {
875
+ /** @description Unique identifier for the object. Use this value as the `{id}` path parameter for `GET /v1/media/{id}`. */
876
+ id: string;
877
+ /**
878
+ * @description String representing the object's type. Objects of the same type share the same value.
879
+ * @enum {string}
880
+ */
881
+ object: "media_upload";
882
+ /** @description Signed URL where the file can be downloaded. Always set on the upload response; may be `null` on retrieval if the underlying blob has been deleted. */
883
+ url: string | null;
884
+ /** @description Time at which the signed `url` expires. Approximately 15 minutes after the response is issued. ISO 8601 datetime. */
885
+ urlExpiresAt: string;
886
+ /** @description MIME type of the uploaded file. */
887
+ mimeType: string;
888
+ /** @description Size of the uploaded file, in bytes. */
889
+ sizeBytes: number;
890
+ /**
891
+ * @description Resource type the file was uploaded for.
892
+ * @enum {string}
893
+ */
894
+ purpose: "board_logo" | "board_hero" | "account_avatar" | "company_logo" | "blog_image";
895
+ };
896
+ /** @description Error envelope, populated once the operation reaches `failed`. `null` otherwise. */
897
+ OperationErrorEnvelope: {
898
+ /** @description Machine-readable error code. */
899
+ code: string;
900
+ /** @description Human-readable error message. */
901
+ message: string;
902
+ /** @description Additional structured details about the error, when present. */
903
+ details?: unknown;
904
+ /** @description Identifier of the request that produced the error. Use this to correlate with platform logs. */
905
+ requestId?: string;
906
+ } | null;
907
+ /** @description Snapshot of the operation's progress, or `null` if the operation does not report progress. */
908
+ OperationProgress: {
909
+ /** @description Progress as a percentage between 0 and 100, when the operation reports a percentage. */
910
+ percent?: number;
911
+ /** @description Human-readable progress message, when available. */
912
+ message?: string;
913
+ /** @description Number of items processed so far, when applicable. */
914
+ processed?: number;
915
+ /** @description Total number of items to process, when known. */
916
+ total?: number;
917
+ } | null;
918
+ OperationResource: {
919
+ /** @description Unique identifier for the object. */
920
+ id: string;
921
+ /**
922
+ * @description String representing the object's type. Objects of the same type share the same value.
923
+ * @enum {string}
924
+ */
925
+ object: "operation";
926
+ /** @description Operation kind, identifying which workflow the operation runs. */
927
+ kind: string;
928
+ /**
929
+ * @description Current state of the operation.
930
+ * @enum {string}
931
+ */
932
+ state: "pending" | "running" | "succeeded" | "failed" | "cancelled";
933
+ /** @description Identifier of the account the operation belongs to. */
934
+ accountId: string;
935
+ progress: components["schemas"]["OperationProgress"];
936
+ /** @description Operation result, populated once the operation reaches `succeeded`. Shape varies by `kind`. */
937
+ result?: unknown;
938
+ error: components["schemas"]["OperationErrorEnvelope"];
939
+ /** @description Time at which the operation was created. ISO 8601 datetime. */
940
+ createdAt: string;
941
+ /** @description Time at which the operation was last updated. ISO 8601 datetime. */
942
+ updatedAt: string;
943
+ /** @description Time at which the operation reached a terminal state, or `null` if it has not yet completed. ISO 8601 datetime. */
944
+ completedAt: string | null;
945
+ /** @description Whether cancellation of the operation has been requested. */
946
+ cancelRequested: boolean;
947
+ /** @description Type of resource the operation acts on, or `null` for resource-less operations. */
948
+ resourceType: string | null;
949
+ /** @description Identifier of the resource the operation acts on, or `null` for resource-less operations. */
950
+ resourceId: string | null;
951
+ /** @description Identifier of the parent operation when this operation is a child of a fan-out, or `null` otherwise. */
952
+ parentOperationId: string | null;
953
+ };
954
+ PatchSettingsBody: {
955
+ /** @description Display name of the board. */
956
+ name?: string;
957
+ /** @description URL slug of the board. Lowercase alphanumeric and hyphens; reserved values (e.g. `admin`, `api`) are rejected. */
958
+ slug?: string;
959
+ /** @description Identifier of the custom domain to use as the primary public URL. */
960
+ primaryDomainId?: string;
961
+ /** @description Media storage ID returned by `POST /v1/media/upload` with `purpose=board_logo`. */
962
+ logoStorageId?: string;
963
+ /** @description Media storage ID returned by `POST /v1/media/upload` with `purpose=board_hero`. */
964
+ heroStorageId?: string;
965
+ /** @description Whether the board sits behind a password gate. Use `POST /v1/settings/password-protection` to set the actual password before enabling. */
966
+ passwordProtectionEnabled?: boolean;
967
+ /** @description Whether candidates can subscribe to email alerts for new jobs. */
968
+ jobAlertsEnabled?: boolean;
969
+ /** @description Whether candidate profiles are enabled on the board. */
970
+ candidatesEnabled?: boolean;
971
+ /** @description Whether employer self-serve flows are enabled. */
972
+ employersEnabled?: boolean;
973
+ /** @description Whether the public blog is exposed. */
974
+ blogEnabled?: boolean;
975
+ /** @description Whether the legal Impressum page is exposed (required in some jurisdictions). */
976
+ impressumEnabled?: boolean;
977
+ /** @description Whether jobs posted by employers from the free tier require admin approval before they appear on the public board. */
978
+ requireApprovalFreeJobs?: boolean;
979
+ /** @description Whether aggregated jobs (e.g. those scraped or imported from upstream sources) require admin approval before they appear on the public board. */
980
+ requireApprovalAggregatedJobs?: boolean;
981
+ /** @description Whether visitors must sign in to view jobs. */
982
+ registrationWallEnabled?: boolean;
983
+ /** @description Whether the public talent directory is enabled. */
984
+ talentDirectoryEnabled?: boolean;
985
+ /** @description Whether the Cavuno-branded footer is displayed on the public board. Plan-gated; lower-tier plans cannot disable this. */
986
+ showCavunoBranding?: boolean;
987
+ /** @description Default expiry, in days, applied to newly published jobs when no `expiresAt` is supplied. */
988
+ defaultJobDurationDays?: number;
989
+ /** @description Public contact email shown on the board. Pass `null` to clear. */
990
+ contactEmail?: string | "" | unknown | unknown;
991
+ /** @description Legal name of the entity operating the board. Pass `null` to clear. */
992
+ companyLegalName?: string | "" | unknown | unknown;
993
+ /** @description Postal address of the entity operating the board. Pass `null` to clear. */
994
+ companyAddress?: string | "" | unknown | unknown;
995
+ /** @description Public company website URL. Pass `null` to clear. */
996
+ companyWebsiteUrl?: string | "" | unknown | unknown;
997
+ /** @description Company X (Twitter) handle or profile URL. Pass `null` to clear. */
998
+ companyXHandle?: string | "" | unknown | unknown;
999
+ /** @description Company Facebook page URL. Pass `null` to clear. */
1000
+ companyFacebookUrl?: string | "" | unknown | unknown;
1001
+ /** @description Company LinkedIn page URL. Pass `null` to clear. */
1002
+ companyLinkedinUrl?: string | "" | unknown | unknown;
1003
+ /** @description Label shown for the talent directory in the public navigation. 1–50 characters. */
1004
+ talentNavLabel?: string;
1005
+ /** @description Custom copy displayed on the password gate. Up to 500 characters. Pass `null` to clear. */
1006
+ passwordProtectionMessage?: string | "" | unknown | unknown;
1007
+ /** @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. */
1008
+ config?: {
1009
+ [key: string]: unknown;
1010
+ };
1011
+ };
1012
+ PublicBlogAdjacentPosts: {
1013
+ /** @enum {string} */
1014
+ object: "blog_adjacent_posts";
1015
+ previous: components["schemas"]["PublicBlogPostSummary"] & unknown;
1016
+ next: components["schemas"]["PublicBlogPostSummary"] & unknown;
1017
+ };
1018
+ PublicBlogAuthor: components["schemas"]["PublicBlogAuthorEmbed"] & {
1019
+ /** @enum {string} */
1020
+ object: "public_blog_author";
1021
+ };
1022
+ PublicBlogAuthorEmbed: {
1023
+ id: string;
1024
+ name: string;
1025
+ slug: string;
1026
+ bio: string | null;
1027
+ avatarUrl: string | null;
1028
+ websiteUrl: string | null;
1029
+ twitterUrl: string | null;
1030
+ linkedinUrl: string | null;
1031
+ githubUrl: string | null;
1032
+ };
1033
+ PublicBlogPost: components["schemas"]["PublicBlogPostSummary"] & {
1034
+ html: string | null;
1035
+ ogImageUrl: string | null;
1036
+ featureImageCaption: string | null;
1037
+ seoTitle: string | null;
1038
+ seoDescription: string | null;
1039
+ redirected: boolean;
1040
+ newSlug: string | null;
1041
+ };
1042
+ PublicBlogPostSummary: {
1043
+ id: string;
1044
+ /** @enum {string} */
1045
+ object: "public_blog_post";
1046
+ title: string;
1047
+ slug: string;
1048
+ featured: boolean;
1049
+ coverUrl: string | null;
1050
+ featureImageAlt: string | null;
1051
+ customExcerpt: string | null;
1052
+ readingTimeMin: number | null;
1053
+ publishedAt: string | null;
1054
+ canonicalUrl: string | null;
1055
+ createdAt: string;
1056
+ authors: components["schemas"]["PublicBlogAuthorEmbed"][];
1057
+ tags: components["schemas"]["PublicBlogTagEmbed"][];
1058
+ };
1059
+ PublicBlogSearchBody: {
1060
+ /** @description Free-text search query. Up to 200 characters. */
1061
+ query: string;
1062
+ /** @description An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results. */
1063
+ cursor?: string | null;
1064
+ /** @description A limit on the number of objects to be returned. Limit can range between 1 and 50. */
1065
+ limit?: number;
1066
+ };
1067
+ PublicBlogTag: components["schemas"]["PublicBlogTagEmbed"] & {
1068
+ /** @enum {string} */
1069
+ object: "public_blog_tag";
1070
+ };
1071
+ PublicBlogTagEmbed: {
1072
+ id: string;
1073
+ name: string;
1074
+ slug: string;
1075
+ description: string | null;
1076
+ };
1077
+ PublicBoardContext: {
1078
+ /** @enum {string} */
1079
+ object: "public_board";
1080
+ /** @description Immutable board identifier (`boards_…`). */
1081
+ id: string;
1082
+ /** @description Mutable canonical board slug. */
1083
+ slug: string;
1084
+ name: string;
1085
+ /** @description Board language (ISO code); defaults to "en". */
1086
+ language: string;
1087
+ logoUrl: string | null;
1088
+ /** @description Active custom-domain hostname, or null. */
1089
+ primaryDomain: string | null;
1090
+ /** @description Whitelabel toggle (default `true`). Render the "Powered by Cavuno" badge unless `false`. */
1091
+ showCavunoBranding: boolean;
1092
+ features: {
1093
+ jobAlerts: boolean;
1094
+ candidates: boolean;
1095
+ employers: boolean;
1096
+ blog: boolean;
1097
+ talentDirectory: boolean;
1098
+ registrationWall: boolean;
1099
+ passwordProtected: boolean;
1100
+ publicJobSubmission: boolean;
1101
+ candidatePaywall: boolean;
1102
+ impressum: boolean;
1103
+ };
1104
+ analytics: {
1105
+ ga4MeasurementId: string | null;
1106
+ gtmId: string | null;
1107
+ metaPixelId: string | null;
1108
+ linkedInPartnerId: string | null;
1109
+ cookieConsentRequired: boolean;
1110
+ };
1111
+ theme: {
1112
+ mode: string;
1113
+ schemeId: string;
1114
+ typography: {
1115
+ fontSans: string;
1116
+ fontHeading?: string | null;
1117
+ };
1118
+ colors: {
1119
+ light: {
1120
+ [key: string]: unknown;
1121
+ };
1122
+ dark: {
1123
+ [key: string]: unknown;
1124
+ };
1125
+ };
1126
+ } | null;
1127
+ };
1128
+ PublicCompaniesSearchBody: {
1129
+ /** @description Free-text search query matched against company name. Up to 200 characters. */
1130
+ query?: string;
1131
+ /** @description An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results. */
1132
+ cursor?: string | null;
1133
+ /** @description A limit on the number of objects to be returned. Limit can range between 1 and 100. */
1134
+ limit?: number;
1135
+ };
1136
+ /** @description Public-only links. The admin URL is intentionally omitted on public-board responses. */
1137
+ PublicCompanyLinks: {
1138
+ /**
1139
+ * Format: uri
1140
+ * @description Canonical public URL for this company on the board, or `null` when no slug is set.
1141
+ */
1142
+ public: string | null;
1143
+ };
1144
+ PublicJob: {
1145
+ /** @description Unique identifier for the object. Use this value as the `{id}` path parameter for the job endpoints (e.g. `GET /v1/jobs/{id}`). */
1146
+ id: string;
1147
+ /**
1148
+ * @description String representing the object's type. Objects of the same type share the same value.
1149
+ * @enum {string}
1150
+ */
1151
+ object: "public_job";
1152
+ /** @description The job title. */
1153
+ title: string;
1154
+ /** @description URL-friendly slug used in public board URLs, or `null` if no slug is set. */
1155
+ slug: string | null;
1156
+ /**
1157
+ * @description Current status of the job. One of `draft`, `published`, `expired`, or `archived`.
1158
+ * @enum {string}
1159
+ */
1160
+ status: "draft" | "published" | "expired" | "archived";
1161
+ /** @description Identifier of the company the job belongs to, or `null` if no company is attached. */
1162
+ companyId: string | null;
1163
+ /**
1164
+ * @description Employment type of the role, or `null` if not specified.
1165
+ * @enum {string|null}
1166
+ */
1167
+ employmentType: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other" | null;
1168
+ /**
1169
+ * @description Whether the role is on-site, hybrid, or fully remote, or `null` if not specified.
1170
+ * @enum {string|null}
1171
+ */
1172
+ remoteOption: "on_site" | "hybrid" | "remote" | null;
1173
+ /**
1174
+ * @description Seniority level of the role, or `null` if not specified.
1175
+ * @enum {string|null}
1176
+ */
1177
+ seniority: "entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive" | null;
1178
+ /** @description Minimum salary in `salaryCurrency` units, or `null` if not specified. */
1179
+ salaryMin: number | null;
1180
+ /** @description Maximum salary in `salaryCurrency` units, or `null` if not specified. */
1181
+ salaryMax: number | null;
1182
+ /** @description Three-letter ISO 4217 currency code for the salary range, or `null` if no salary is specified. */
1183
+ salaryCurrency: string | null;
1184
+ /**
1185
+ * @description Period the salary range is quoted against, or `null` if no salary is specified.
1186
+ * @enum {string|null}
1187
+ */
1188
+ salaryTimeframe: "per_year" | "per_month" | "per_week" | "per_day" | "per_hour" | null;
1189
+ /** @description Whether the job appears in featured slots on the public board. */
1190
+ isFeatured: boolean;
1191
+ /** @description Time at which the job was first published, or `null` if not yet published. ISO 8601 datetime. */
1192
+ publishedAt: string | null;
1193
+ /** @description Time at which the job expires, or `null` if no expiry is set. ISO 8601 datetime. */
1194
+ expiresAt: string | null;
1195
+ /** @description Time at which the job was created. ISO 8601 datetime. */
1196
+ createdAt: string;
1197
+ /** @description Time at which the job was last updated. ISO 8601 datetime. */
1198
+ updatedAt: string;
1199
+ links: components["schemas"]["PublicJobLinks"];
1200
+ /** @description Long-form description of the role, or `null` if not specified. */
1201
+ description: string | null;
1202
+ /** @description Where candidates apply, or `null` if not specified. An HTTPS URL or `mailto:` URI. */
1203
+ applicationUrl: string | null;
1204
+ /** @description Hierarchical permit selection authored by the board owner. The three `remoteWorkPermit*` and `remoteWorldwide` fields are read-only derived projections. */
1205
+ remotePermits: {
1206
+ type: string;
1207
+ value: string;
1208
+ }[];
1209
+ /** @description Read-only — derived from `remotePermits`. `true` only when the authored selection is a single `{type:"worldwide"}` entry. */
1210
+ remoteWorldwide: boolean | null;
1211
+ /** @description Hierarchical timezone selection. The flat `remoteAllowedTzOffsets` field below is the read-only derived projection. */
1212
+ remoteTimezones: {
1213
+ type: string;
1214
+ value: string;
1215
+ plusMinus?: number;
1216
+ }[];
1217
+ /** @description Read-only — derived from `remoteTimezones`. UTC hour offsets used by the job-search index. */
1218
+ remoteAllowedTzOffsets: number[];
1219
+ /** @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. */
1220
+ remoteWorkPermitCountryCodes: string[];
1221
+ /** @description Read-only — derived from `remotePermits` (subdivision entries only). ISO 3166-2 codes. */
1222
+ remoteWorkPermitSubdivisionCodes: string[];
1223
+ /**
1224
+ * @description Whether the employer sponsors visas for remote candidates. One of `yes`, `no`, or `unknown`.
1225
+ * @enum {string}
1226
+ */
1227
+ remoteSponsorship: "yes" | "no" | "unknown";
1228
+ /** @description Required education credentials. Each value is one of `high_school`, `associate_degree`, `bachelor_degree`, `professional_certificate`, `postgraduate_degree`, or `no_requirements`. */
1229
+ educationRequirements: ("high_school" | "associate_degree" | "bachelor_degree" | "professional_certificate" | "postgraduate_degree" | "no_requirements")[];
1230
+ /** @description Minimum required experience in months, or `null` if not specified. */
1231
+ experienceMonths: number | null;
1232
+ /** @description If `true`, equivalent experience may substitute for the listed education requirements. `null` if not specified. */
1233
+ experienceInPlaceOfEducation: boolean | null;
1234
+ /**
1235
+ * @description Period denominator for `inOfficeFrequency`, or `null` if not specified.
1236
+ * @enum {string|null}
1237
+ */
1238
+ inOfficePeriod: "per_week" | "per_month" | "per_year" | null;
1239
+ /** @description How often the candidate must be in-office over `inOfficePeriod`, or `null` if not specified. */
1240
+ inOfficeFrequency: number | null;
1241
+ company: components["schemas"]["JobCompany"];
1242
+ /** @description Physical office locations associated with the job. */
1243
+ officeLocations: components["schemas"]["JobOfficeLocation"][];
1244
+ /** @description Resolved job categories (slug + board display name) — same shape as the card; names joined server-side. */
1245
+ categories: {
1246
+ slug: string;
1247
+ name: string;
1248
+ }[];
1249
+ /** @description Resolved job skills (slug + board display name). */
1250
+ skills: {
1251
+ slug: string;
1252
+ name: string;
1253
+ }[];
1254
+ /** @description Place ancestor chain (country → region → city) for the breadcrumb; each `{slug,name}` links to `/jobs/locations/:slug`. Source-language. */
1255
+ placeHierarchy: {
1256
+ slug: string;
1257
+ name: string;
1258
+ }[];
1259
+ };
1260
+ PublicJobAlertConfirmation: {
1261
+ /** @enum {string} */
1262
+ object: "job_alert_confirmation";
1263
+ /**
1264
+ * @description Outcome of the confirmation. Always returned with HTTP 200 so the consumer renders by status (the token may be valid, stale, or unknown).
1265
+ * @enum {string}
1266
+ */
1267
+ status: "confirmed" | "already_confirmed" | "expired" | "not_found";
1268
+ };
1269
+ PublicJobAlertManageResult: {
1270
+ /** @enum {string} */
1271
+ object: "job_alert_manage_result";
1272
+ success: boolean;
1273
+ };
1274
+ PublicJobAlertManageState: {
1275
+ /** @enum {string} */
1276
+ object: "job_alert_manage_state";
1277
+ email: string;
1278
+ confirmed: boolean;
1279
+ unsubscribed: boolean;
1280
+ preferences: {
1281
+ id: string;
1282
+ label: string | null;
1283
+ frequency: string;
1284
+ isActive: boolean;
1285
+ filters: {
1286
+ [key: string]: unknown;
1287
+ };
1288
+ manageToken: string;
1289
+ }[];
1290
+ };
1291
+ PublicJobAlertResend: {
1292
+ /** @enum {string} */
1293
+ object: "job_alert_confirmation_resend";
1294
+ /** @enum {string} */
1295
+ status: "sent" | "not_found" | "already_confirmed" | "throttled" | "send_failed";
1296
+ };
1297
+ PublicJobAlertSubscription: {
1298
+ /** @enum {string} */
1299
+ object: "job_alert_subscription";
1300
+ /**
1301
+ * @description `created` on a new subscription; `duplicate` if it existed.
1302
+ * @enum {string}
1303
+ */
1304
+ status: "created" | "duplicate";
1305
+ /** @description True when a double-opt-in confirmation email was sent. */
1306
+ requiresConfirmation: boolean;
1307
+ /** @description True if the subscriber was already email-confirmed. */
1308
+ confirmed: boolean;
1309
+ };
1310
+ PublicJobCard: {
1311
+ id: string;
1312
+ /** @enum {string} */
1313
+ object: "job_card";
1314
+ slug: string;
1315
+ title: string;
1316
+ /**
1317
+ * Format: date-time
1318
+ * @description ISO 8601 publish timestamp, or `null` if unpublished.
1319
+ */
1320
+ publishedAt: string | null;
1321
+ /** @enum {string|null} */
1322
+ employmentType: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other" | null;
1323
+ /** @enum {string|null} */
1324
+ remoteOption: "on_site" | "hybrid" | "remote" | null;
1325
+ /** @description Display region label for remote jobs (e.g. "United States", "Worldwide"); `null` for non-remote jobs. */
1326
+ remoteLocationLabel: string | null;
1327
+ salaryMin: number | null;
1328
+ salaryMax: number | null;
1329
+ salaryCurrency: string | null;
1330
+ salaryTimeframe: string | null;
1331
+ isFeatured: boolean;
1332
+ locationLabel: string | null;
1333
+ /** @description Embedded company summary, or `null` if none is attached. */
1334
+ company: {
1335
+ slug: string;
1336
+ name: string;
1337
+ logoUrl: string | null;
1338
+ } | null;
1339
+ categories: {
1340
+ slug: string;
1341
+ name: string;
1342
+ }[];
1343
+ skills: {
1344
+ slug: string;
1345
+ name: string;
1346
+ }[];
1347
+ links: {
1348
+ /**
1349
+ * Format: uri
1350
+ * @description Canonical public URL for this job, or `null` when no stable URL can be assembled.
1351
+ */
1352
+ public: string | null;
1353
+ };
1354
+ /** @description Long-form description (HTML), or `null`. Present ONLY when requested via `?fields=+description`; absent on the default slim card. */
1355
+ description?: string | null;
1356
+ };
1357
+ /** @description Public-only links. The admin URL is intentionally omitted on public-board responses. */
1358
+ PublicJobLinks: {
1359
+ /**
1360
+ * Format: uri
1361
+ * @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).
1362
+ */
1363
+ public: string | null;
1364
+ };
1365
+ PublicPlace: {
1366
+ /** @enum {string} */
1367
+ object: "place";
1368
+ /** @description Stable place identity (locations-tree edge endpoint). */
1369
+ id: string;
1370
+ /** @description Parent place's `id`; `null` for a root place. */
1371
+ parentId: string | null;
1372
+ /** @description Public slug (links to `/jobs/locations/:slug`); `null` if unslugged. */
1373
+ slug: string | null;
1374
+ name: string;
1375
+ placeType: string;
1376
+ countryCode: string | null;
1377
+ regionCode: string | null;
1378
+ /** @description Live published-job count for this place. */
1379
+ jobCount: number;
1380
+ };
1381
+ PublicSearchJobsBody: {
1382
+ /** @description Free-text search query matched against job title and description. Up to 200 characters. */
1383
+ query?: string;
1384
+ /** @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. */
1385
+ filters?: {
1386
+ /** @description Only return jobs at any of the given company IDs. Up to 10 values. */
1387
+ companyId?: string[];
1388
+ /** @description Only return jobs with any of the given remote-work options. Up to 10 values. */
1389
+ remoteOption?: ("on_site" | "hybrid" | "remote")[];
1390
+ /** @description Only return jobs with any of the given employment types. Up to 10 values. */
1391
+ employmentType?: ("full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other")[];
1392
+ /** @description Only return jobs at any of the given seniority levels. Up to 10 values. */
1393
+ seniority?: ("entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive")[];
1394
+ /** @description Range filter on the job's `publishedAt` timestamp. */
1395
+ publishedAt?: {
1396
+ /**
1397
+ * Format: date-time
1398
+ * @description Only return jobs published at or after this ISO 8601 datetime.
1399
+ */
1400
+ gte?: string;
1401
+ /**
1402
+ * Format: date-time
1403
+ * @description Only return jobs published at or before this ISO 8601 datetime.
1404
+ */
1405
+ lte?: string;
1406
+ };
1407
+ /** @description Only return jobs near the place with this slug (geo radius search). Unresolvable slugs are ignored. */
1408
+ location?: string;
1409
+ /** @description Search radius in kilometres around `location` (10–250; default 50). Ignored without `location`. */
1410
+ radius?: number;
1411
+ };
1412
+ /** @description An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results. */
1413
+ cursor?: string;
1414
+ /**
1415
+ * @description A limit on the number of objects to be returned. Limit can range between 1 and 100.
1416
+ * @example 20
1417
+ */
1418
+ limit?: number;
1419
+ /**
1420
+ * @description The number of jobs to skip — the storefront page offset. Takes precedence over `cursor`. `offset + limit` may not exceed 10,000.
1421
+ * @example 0
1422
+ */
1423
+ offset?: number;
1424
+ };
1425
+ PublicTaxonomyResolution: {
1426
+ /** @enum {string} */
1427
+ object: "taxonomy_resolution";
1428
+ /** @enum {string} */
1429
+ type: "category" | "skill" | "place";
1430
+ /** @description Immutable English source slug — the semantic-search key. */
1431
+ sourceSlug: string;
1432
+ /** @description Board-language URL slug (the `<link rel=canonical>` target). */
1433
+ canonicalSlug: string;
1434
+ /** @description Board-language display name. */
1435
+ displayName: string;
1436
+ /** @description The canonical slug to emit a 308 redirect to when the inbound slug differs; `null` otherwise. */
1437
+ redirectTo: string | null;
1438
+ geo: components["schemas"]["TaxonomyGeo"];
1439
+ };
1440
+ PublicVerifyBoardPasswordBody: {
1441
+ /** @description The board password. */
1442
+ password: string;
1443
+ };
1444
+ PublishJobBody: {
1445
+ /**
1446
+ * Format: date-time
1447
+ * @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.
1448
+ */
1449
+ expiresAt?: string | null;
1450
+ };
1451
+ RedirectResolution: {
1452
+ /** @enum {string} */
1453
+ object: "redirect_resolution";
1454
+ path: string;
1455
+ /** @description The redirect target (board-relative), or `null` when no redirect matches. The consumer 308s to `target`, or 404s when `null`. */
1456
+ target: string | null;
1457
+ };
1458
+ RemotePermitTaxonomyEntry: {
1459
+ /** @description Discriminator. One of: `worldwide`, `world_region`, `continent`, `region`, `subregion`, `custom`, `country`, `subdivision`. */
1460
+ type: string;
1461
+ /** @description Canonical value for the type. ISO 3166-1 alpha-2 for `country`, ISO 3166-2 for `subdivision`, etc. */
1462
+ value: string;
1463
+ /** @description Human-readable display label. */
1464
+ label: string;
1465
+ };
1466
+ RemoteTimezoneTaxonomyEntry: {
1467
+ /** @description Discriminator. One of: `all`, `world_region`, `continent`, `region`, `subregion`, `country`, `timezone`. */
1468
+ type: string;
1469
+ /** @description Canonical value for the type. ISO 3166-1 alpha-2 for `country`, IANA name (e.g. `Europe/London`) for `timezone`, etc. */
1470
+ value: string;
1471
+ /** @description Human-readable display label. */
1472
+ label: string;
1473
+ };
1474
+ ResourceLinks: {
1475
+ /**
1476
+ * Format: uri
1477
+ * @description Canonical public URL for this resource on the board. Honours the configured custom domain when present, otherwise uses the board subdomain.
1478
+ */
1479
+ public: string;
1480
+ /**
1481
+ * Format: uri
1482
+ * @description URL inside the Cavuno app where the authenticated owner can manage this resource.
1483
+ */
1484
+ admin: string;
1485
+ };
1486
+ RevokeRequest: {
1487
+ /** @description The access or refresh token to revoke. */
1488
+ token: string;
1489
+ /**
1490
+ * @description Hint indicating whether `token` is an `access_token` or `refresh_token`. Optional.
1491
+ * @enum {string}
1492
+ */
1493
+ token_type_hint?: "access_token" | "refresh_token";
1494
+ /** @description OAuth client identifier. May be supplied here or via HTTP Basic authentication. */
1495
+ client_id?: string;
1496
+ /** @description OAuth client secret. May be supplied here or via HTTP Basic authentication. */
1497
+ client_secret?: string;
1498
+ };
1499
+ SaveJobBody: {
1500
+ jobId: string;
1501
+ };
1502
+ SavedJob: {
1503
+ /** @description Saved-job row ID. */
1504
+ id: string;
1505
+ /** @enum {string} */
1506
+ object: "saved_job";
1507
+ /** @description The saved job — also the DELETE path key. */
1508
+ jobId: string;
1509
+ /** Format: date-time */
1510
+ savedAt: string;
1511
+ job: components["schemas"]["PublicJob"];
1512
+ };
1513
+ SearchBlogPostsBody: {
1514
+ query?: string;
1515
+ /** @enum {string} */
1516
+ status?: "draft" | "scheduled" | "published";
1517
+ cursor?: string | null;
1518
+ limit?: number;
1519
+ };
1520
+ SearchCompaniesBody: {
1521
+ /** @description Free-text search query matched against company name. Up to 200 characters. */
1522
+ query?: string;
1523
+ /** @description An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results. */
1524
+ cursor?: string | null;
1525
+ /**
1526
+ * @description A limit on the number of objects to be returned. Limit can range between 1 and 100.
1527
+ * @example 20
1528
+ */
1529
+ limit?: number;
1530
+ };
1531
+ SearchJobsBody: {
1532
+ /** @description Free-text search query matched against job title and description. Up to 200 characters. */
1533
+ query?: string;
1534
+ /** @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. */
1535
+ filters?: {
1536
+ /** @description Only return jobs in any of the given statuses. Up to 10 values. */
1537
+ status?: ("draft" | "published" | "expired" | "archived")[];
1538
+ /** @description Only return jobs at any of the given company IDs. Up to 10 values. */
1539
+ companyId?: string[];
1540
+ /** @description Only return jobs with any of the given remote-work options. Up to 10 values. */
1541
+ remoteOption?: ("on_site" | "hybrid" | "remote")[];
1542
+ /** @description Only return jobs with any of the given employment types. Up to 10 values. */
1543
+ employmentType?: ("full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other")[];
1544
+ /** @description Only return jobs at any of the given seniority levels. Up to 10 values. */
1545
+ seniority?: ("entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive")[];
1546
+ /** @description Range filter on the job's `publishedAt` timestamp. */
1547
+ publishedAt?: {
1548
+ /**
1549
+ * Format: date-time
1550
+ * @description Only return jobs published at or after this ISO 8601 datetime.
1551
+ */
1552
+ gte?: string;
1553
+ /**
1554
+ * Format: date-time
1555
+ * @description Only return jobs published at or before this ISO 8601 datetime.
1556
+ */
1557
+ lte?: string;
1558
+ };
1559
+ };
1560
+ /** @description An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results. */
1561
+ cursor?: string;
1562
+ /**
1563
+ * @description A limit on the number of objects to be returned. Limit can range between 1 and 100.
1564
+ * @example 20
1565
+ */
1566
+ limit?: number;
1567
+ };
1568
+ SettingsAdsenseBody: {
1569
+ /** @description Whether AdSense placements are rendered on the public board. */
1570
+ adsenseEnabled?: boolean;
1571
+ /** @description AdSense publisher ID in `ca-pub-XXXXXXXXXXXXXXXX` format. Pass an empty string or `null` to clear. */
1572
+ adsenseClientId?: string | "" | unknown | unknown;
1573
+ /** @description Map of placement key to slot configuration. Placement keys are lowercase alphanumeric with `-`, `_`, `.`, or `:`. */
1574
+ adsenseSlots?: {
1575
+ [key: string]: components["schemas"]["SettingsAdsenseSlot"];
1576
+ };
1577
+ /** @description Contents to serve from `/ads.txt`. Up to 2,000 characters. Pass an empty string or `null` to clear. */
1578
+ adsTxt?: string | "" | unknown | unknown;
1579
+ };
1580
+ SettingsAdsenseSlot: {
1581
+ /** @description Whether this placement is rendered. */
1582
+ enabled: boolean;
1583
+ /** @description Ten-digit AdSense slot ID. Pass an empty string or `null` to clear. */
1584
+ slotId: string | "" | unknown | unknown;
1585
+ /** @description AdSense layout type for the placement. */
1586
+ layout?: ("auto" | "in-article" | "in-feed" | "fluid") | "" | unknown | unknown;
1587
+ /** @description AdSense ad format. */
1588
+ format?: ("auto" | "horizontal" | "vertical" | "rectangle" | "responsive") | "" | unknown | unknown;
1589
+ /** @description Visual style override for the placement. */
1590
+ style?: ("default" | "light" | "dark" | "contrast") | "" | unknown | unknown;
1591
+ /** @description How often the placement is shown (e.g. once every N items). */
1592
+ frequency?: number | unknown | unknown;
1593
+ };
1594
+ SettingsPasswordProtectionBody: {
1595
+ /** @description Plaintext password used to gate the public board. Must be at least 8 characters. Stored hashed and encrypted server-side. */
1596
+ password: string;
1597
+ };
1598
+ SettingsPaywallBody: {
1599
+ /** @description Whether the job-access paywall is enforced on the public board. */
1600
+ jobAccessPaywallEnabled: boolean;
1601
+ /** @description Number of jobs visible before the paywall locks the rest. Range 1–500. */
1602
+ jobAccessPreviewCount?: number;
1603
+ /** @description Heading shown on the paywall. Up to 120 characters. */
1604
+ jobAccessLockHeading?: string;
1605
+ /** @description Body copy shown on the paywall. Up to 600 characters. */
1606
+ jobAccessLockDescription?: string;
1607
+ /** @description Call-to-action label shown on the paywall. Up to 60 characters. */
1608
+ jobAccessButtonText?: string;
1609
+ /** @description Fine-print disclaimer shown beneath the call-to-action. Up to 200 characters. */
1610
+ jobAccessDisclaimerText?: string;
1611
+ /** @description Label appended to the monthly price (e.g. `/month`). Up to 60 characters. */
1612
+ jobAccessPerMonthLabel?: string;
1613
+ /** @description Template string used to render the savings line for annual plans. Up to 120 characters. */
1614
+ jobAccessSavingsTemplate?: string;
1615
+ /** @description Three-letter ISO 4217 currency code for paywall pricing. */
1616
+ jobAccessCurrency?: string;
1617
+ /** @description Stripe product ID associated with the paywall plan. Pass `null` to clear. */
1618
+ jobAccessStripeProductId?: string | unknown | unknown;
1619
+ /** @description Stripe billing-portal configuration ID used for self-serve plan management. Pass `null` to clear. */
1620
+ jobAccessStripePortalConfigId?: string | unknown | unknown;
1621
+ };
1622
+ /** @description Geo for place resolutions; `null` for category/skill. */
1623
+ TaxonomyGeo: {
1624
+ lat: number | null;
1625
+ lng: number | null;
1626
+ countryCode: string | null;
1627
+ regionCode: string | null;
1628
+ region: string | null;
1629
+ city: string | null;
1630
+ locality: string | null;
1631
+ placeType: string | null;
1632
+ } | null;
1633
+ TokenRequest: {
1634
+ /**
1635
+ * @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.
1636
+ * @enum {string}
1637
+ */
1638
+ grant_type: "authorization_code" | "refresh_token";
1639
+ /** @description Authorization code returned from the authorization endpoint. Required when `grant_type` is `authorization_code`. */
1640
+ code?: string;
1641
+ /** @description Redirect URI used in the original authorization request. Must match exactly. Required when `grant_type` is `authorization_code`. */
1642
+ redirect_uri?: string;
1643
+ /** @description PKCE code verifier whose `S256` hash matches the original `code_challenge`. Required when `grant_type` is `authorization_code`. */
1644
+ code_verifier?: string;
1645
+ /** @description Refresh token previously issued. Required when `grant_type` is `refresh_token`. Refresh tokens are single-use; reusing one revokes the entire token chain. */
1646
+ refresh_token?: string;
1647
+ /** @description OAuth client identifier. May be supplied here or via HTTP Basic authentication. */
1648
+ client_id?: string;
1649
+ /** @description OAuth client secret. May be supplied here or via HTTP Basic authentication. */
1650
+ client_secret?: string;
1651
+ /** @description Optional scope narrowing. Currently ignored — issued tokens always carry the full scope registered for the client. */
1652
+ scope?: string;
1653
+ };
1654
+ TokenResponse: {
1655
+ /** @description Newly issued access token. Use as a `Bearer` token in the `Authorization` header. */
1656
+ access_token: string;
1657
+ /**
1658
+ * @description Always `Bearer`.
1659
+ * @enum {string}
1660
+ */
1661
+ token_type: "Bearer";
1662
+ /** @description Lifetime of the access token, in seconds. */
1663
+ expires_in: number;
1664
+ /** @description Newly issued refresh token. Single-use; reusing it revokes the entire token chain. */
1665
+ refresh_token: string;
1666
+ /** @description Space-separated list of scopes granted on the issued token. */
1667
+ scope: string;
1668
+ };
1669
+ UpdateAuthorBody: {
1670
+ /** @description URL-friendly slug for the author. Auto-generated from `name` when omitted. */
1671
+ slug?: string;
1672
+ /** @description Short biography for the author. Sanitized HTML. */
1673
+ bio?: string;
1674
+ /**
1675
+ * Format: email
1676
+ * @description The author's email address.
1677
+ */
1678
+ email?: string;
1679
+ /**
1680
+ * @description Author visibility status. One of `active` or `inactive`.
1681
+ * @enum {string}
1682
+ */
1683
+ status?: "active" | "inactive";
1684
+ /** @description Storage ID of an uploaded avatar image (from `POST /v1/media/upload`). Pass `null` to clear an existing avatar. */
1685
+ avatarStorageId?: string | null;
1686
+ /** @description The author's personal website URL. Normalized to a canonical URL when stored. */
1687
+ websiteUrl?: string;
1688
+ /** @description The author's X (Twitter) profile URL. Stored as the canonical `https://x.com/<handle>` URL. */
1689
+ twitterUrl?: string;
1690
+ /** @description The author's LinkedIn profile URL. */
1691
+ linkedinUrl?: string;
1692
+ /** @description The author's GitHub profile URL. */
1693
+ githubUrl?: string;
1694
+ /** @description SEO meta title for the author page. */
1695
+ metaTitle?: string;
1696
+ /** @description SEO meta description for the author page. */
1697
+ metaDescription?: string;
1698
+ /** @description The author's display name. */
1699
+ name?: string;
1700
+ };
1701
+ UpdateBlogPostBody: {
1702
+ slug?: string;
1703
+ html?: string;
1704
+ customExcerpt?: string;
1705
+ readingTimeMin?: number;
1706
+ featured?: boolean;
1707
+ authorIds?: string[];
1708
+ tagIds?: string[];
1709
+ coverStorageId?: string | null;
1710
+ ogImageStorageId?: string | null;
1711
+ featureImageAlt?: string;
1712
+ featureImageCaption?: string;
1713
+ seoTitle?: string;
1714
+ seoDescription?: string;
1715
+ /** Format: uri */
1716
+ canonicalUrl?: string;
1717
+ /** Format: date-time */
1718
+ publishedAt?: string;
1719
+ title?: string;
1720
+ /** @enum {string} */
1721
+ status?: "draft" | "scheduled" | "published";
1722
+ };
1723
+ UpdateCompanyBody: {
1724
+ /** @description Public company website URL. Normalized to a canonical apex domain when stored. */
1725
+ website?: string;
1726
+ /** @description One-line summary of the company. Up to 280 characters. */
1727
+ summary?: string;
1728
+ /** @description Long-form description of the company. Up to 25,000 characters. */
1729
+ description?: string;
1730
+ /** @description X (Twitter) profile URL or handle. Stored as the canonical handle. */
1731
+ xUrl?: string;
1732
+ /** @description LinkedIn company page URL. */
1733
+ linkedinUrl?: string;
1734
+ /** @description Facebook company page URL. */
1735
+ facebookUrl?: string;
1736
+ /** @description The company's display name. */
1737
+ name?: string;
1738
+ /** @description URL-friendly slug for the company. */
1739
+ slug?: string;
1740
+ };
1741
+ UpdateJobBody: {
1742
+ /** @description Identifier of the company the job belongs to. */
1743
+ companyId?: string;
1744
+ /** @description Long-form description of the role. Up to 25,000 characters. */
1745
+ description?: string;
1746
+ /** @description URL-friendly slug for the job. Auto-generated from `title` when omitted. */
1747
+ slug?: string;
1748
+ /**
1749
+ * @description Employment type of the role.
1750
+ * @enum {string}
1751
+ */
1752
+ employmentType?: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other";
1753
+ /**
1754
+ * @description Whether the role is on-site, hybrid, or fully remote.
1755
+ * @enum {string}
1756
+ */
1757
+ remoteOption?: "on_site" | "hybrid" | "remote";
1758
+ /** @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. */
1759
+ remotePermits?: {
1760
+ /** @enum {string} */
1761
+ type: "worldwide" | "world_region" | "continent" | "region" | "subregion" | "subdivision" | "country" | "custom";
1762
+ value: string;
1763
+ }[];
1764
+ /** @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. */
1765
+ remoteTimezones?: {
1766
+ /** @enum {string} */
1767
+ type: "all" | "world_region" | "continent" | "region" | "subregion" | "country" | "timezone";
1768
+ value: string;
1769
+ plusMinus?: number;
1770
+ }[];
1771
+ /**
1772
+ * @description Whether the employer sponsors visas for remote candidates. One of `yes`, `no`, or `unknown`.
1773
+ * @enum {string}
1774
+ */
1775
+ remoteSponsorship?: "yes" | "no" | "unknown";
1776
+ /**
1777
+ * @description Seniority level of the role.
1778
+ * @enum {string}
1779
+ */
1780
+ seniority?: "entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive";
1781
+ /** @description Where candidates apply. Accepts an HTTPS URL, a `mailto:` URI, or a bare email address (which is normalized to `mailto:` form). */
1782
+ applicationUrl?: string;
1783
+ /** @description Minimum salary, in `salaryCurrency` units. */
1784
+ salaryMin?: number;
1785
+ /** @description Maximum salary, in `salaryCurrency` units. */
1786
+ salaryMax?: number;
1787
+ /** @description Three-letter ISO 4217 currency code for `salaryMin` and `salaryMax`. */
1788
+ salaryCurrency?: string;
1789
+ /**
1790
+ * @description Period the `salaryMin` and `salaryMax` figures are quoted against.
1791
+ * @enum {string}
1792
+ */
1793
+ salaryTimeframe?: "per_year" | "per_month" | "per_week" | "per_day" | "per_hour";
1794
+ /** @description Whether the job appears in featured slots on the public board. */
1795
+ isFeatured?: boolean;
1796
+ /** @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. */
1797
+ expiresAt?: number | unknown | unknown;
1798
+ /** @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. */
1799
+ publishedAt?: number;
1800
+ /** @description Required education credentials. Each value is one of `high_school`, `associate_degree`, `bachelor_degree`, `professional_certificate`, `postgraduate_degree`, or `no_requirements`. */
1801
+ educationRequirements?: ("high_school" | "associate_degree" | "bachelor_degree" | "professional_certificate" | "postgraduate_degree" | "no_requirements")[];
1802
+ /** @description Minimum required experience, expressed in months. */
1803
+ experienceMonths?: number;
1804
+ /** @description If `true`, equivalent experience may substitute for the listed education requirements. */
1805
+ experienceInPlaceOfEducation?: boolean;
1806
+ /**
1807
+ * @description Period denominator for `inOfficeFrequency`.
1808
+ * @enum {string}
1809
+ */
1810
+ inOfficePeriod?: "per_week" | "per_month" | "per_year";
1811
+ /** @description How often the candidate must be in-office over `inOfficePeriod`. */
1812
+ inOfficeFrequency?: number;
1813
+ /** @description Physical office locations associated with the job. Each entry is forward-geocoded server-side; a country mismatch returns `400 jobs_unresolvable_location`. */
1814
+ officeLocations?: components["schemas"]["JobOfficeLocationInput"][];
1815
+ /** @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. */
1816
+ externalId?: string;
1817
+ /** @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. */
1818
+ customFieldValues?: {
1819
+ [key: string]: string | string[] | boolean | number | unknown | unknown;
1820
+ };
1821
+ /** @description The job title. */
1822
+ title?: string;
1823
+ };
1824
+ UpdateTagBody: {
1825
+ /** @description URL-friendly slug for the tag. Auto-generated from `name` when omitted. */
1826
+ slug?: string;
1827
+ /** @description Description for the tag. Sanitized HTML. */
1828
+ description?: string;
1829
+ /**
1830
+ * @description Tag visibility. One of `public` or `internal`.
1831
+ * @enum {string}
1832
+ */
1833
+ visibility?: "public" | "internal";
1834
+ /** @description SEO meta title for the tag page. */
1835
+ metaTitle?: string;
1836
+ /** @description SEO meta description for the tag page. */
1837
+ metaDescription?: string;
1838
+ /** @description The display name of the tag. */
1839
+ name?: string;
1840
+ };
1841
+ Usage: {
1842
+ /** @description Unique identifier for the object. Equal to the account ID — usage is a per-account singleton. */
1843
+ id: string;
1844
+ /**
1845
+ * @description String representing the object's type. Objects of the same type share the same value.
1846
+ * @enum {string}
1847
+ */
1848
+ object: "usage";
1849
+ /** @description Number of jobs currently in `published` status. */
1850
+ activeJobs: number;
1851
+ /** @description Plan-enforced cap on the number of published jobs. */
1852
+ activeJobsLimit: number;
1853
+ /** @description Number of additional jobs the account may publish before hitting the limit. */
1854
+ available: number;
1855
+ /** @description Slug of the account's current plan. */
1856
+ plan: string;
1857
+ };
1858
+ };
1859
+ responses: never;
1860
+ parameters: never;
1861
+ requestBodies: never;
1862
+ headers: never;
1863
+ pathItems: never;
1864
+ }
1865
+
1866
+ type Schemas = components['schemas'];
1867
+
1
1868
  /**
2
1869
  * Stripe-shaped success envelopes (`01-conventions.md` §5.1). The
3
1870
  * server MAY add top-level fields; consumers MUST ignore unknown
@@ -34,146 +1901,16 @@ interface SearchEnvelope<T> extends StorefrontPagination {
34
1901
  data: T[];
35
1902
  }
36
1903
 
37
- type RemoteOption = 'on_site' | 'hybrid' | 'remote';
38
- type EmploymentType = 'full_time' | 'part_time' | 'contract' | 'internship' | 'temporary' | 'volunteer' | 'other';
39
- type Seniority = 'entry_level' | 'associate' | 'mid_level' | 'senior' | 'lead' | 'principal' | 'director' | 'executive';
40
- type EducationRequirement = 'high_school' | 'associate_degree' | 'bachelor_degree' | 'professional_certificate' | 'postgraduate_degree' | 'no_requirements';
41
- interface OfficeLocation {
42
- countryCode: string | null;
43
- country: string | null;
44
- locality: string | null;
45
- city: string | null;
46
- region: string | null;
47
- regionCode: string | null;
48
- postalCode: string | null;
49
- displayName: string | null;
50
- }
51
- interface JobCompany {
52
- id: string;
53
- name: string | null;
54
- slug: string | null;
55
- logoUrl: string | null;
56
- website: string | null;
57
- }
58
- interface RemotePermit {
59
- type: string;
60
- value: string;
61
- }
62
- interface RemoteTimezone {
63
- type: string;
64
- value: string;
65
- plusMinus?: number;
66
- }
67
- interface PublicJob {
68
- id: string;
69
- object: 'public_job';
70
- title: string;
71
- slug: string | null;
72
- status: string;
73
- companyId: string | null;
74
- employmentType: string | null;
75
- remoteOption: string | null;
76
- seniority: string | null;
77
- salaryMin: number | null;
78
- salaryMax: number | null;
79
- salaryCurrency: string | null;
80
- salaryTimeframe: string | null;
81
- isFeatured: boolean;
82
- publishedAt: string | null;
83
- expiresAt: string | null;
84
- createdAt: string;
85
- updatedAt: string;
86
- description: string | null;
87
- applicationUrl: string | null;
88
- /** Canonical hierarchical permit selection. */
89
- remotePermits: RemotePermit[];
90
- /** Read-only — derived from `remotePermits`. */
91
- remoteWorldwide: boolean | null;
92
- /** Canonical hierarchical timezone selection. */
93
- remoteTimezones: RemoteTimezone[];
94
- /** Read-only — derived from `remoteTimezones`. */
95
- remoteAllowedTzOffsets: number[];
96
- /** Read-only — derived from `remotePermits`. */
97
- remoteWorkPermitCountryCodes: string[];
98
- /** Read-only — derived from `remotePermits`. */
99
- remoteWorkPermitSubdivisionCodes: string[];
100
- remoteSponsorship: 'yes' | 'no' | 'unknown';
101
- educationRequirements: EducationRequirement[];
102
- experienceMonths: number | null;
103
- experienceInPlaceOfEducation: boolean | null;
104
- inOfficePeriod: 'per_week' | 'per_month' | 'per_year' | null;
105
- inOfficeFrequency: number | null;
106
- company: JobCompany | null;
107
- officeLocations: OfficeLocation[];
108
- /** Resolved taxonomy — same `{slug,name}` shape as `PublicJobCard`; names joined server-side. */
109
- categories: Array<{
110
- slug: string;
111
- name: string;
112
- }>;
113
- skills: Array<{
114
- slug: string;
115
- name: string;
116
- }>;
117
- /**
118
- * Place ancestor chain (country → region → city) for the breadcrumb. Each
119
- * `slug` is the English SOURCE slug — the key `taxonomy.places.resolve()`
120
- * accepts. On a localized board it may differ from the canonical
121
- * board-language URL slug (the board router 308-redirects the source slug to
122
- * the canonical one); link via `/jobs/locations/:slug`.
123
- */
124
- placeHierarchy: Array<{
125
- slug: string;
126
- name: string;
127
- }>;
128
- links: {
129
- public: string | null;
130
- };
131
- }
132
- /**
133
- * The slim listing card (ADR-0037 §1) returned by `jobs.list` / `jobs.search`
134
- * / `companies.listJobs`. Full enrichment (description, officeLocations, the
135
- * structured remote blocks, …) lives on `jobs.retrieve` (`PublicJob`).
136
- * Transcribed from `serializeJobCard`.
137
- */
138
- interface PublicJobCard {
139
- id: string;
140
- object: 'job_card';
141
- slug: string;
142
- title: string;
143
- publishedAt: string | null;
144
- employmentType: string | null;
145
- remoteOption: string | null;
146
- /** Remote-region label for remote jobs (e.g. "Worldwide"); `null` otherwise. */
147
- remoteLocationLabel: string | null;
148
- salaryMin: number | null;
149
- salaryMax: number | null;
150
- salaryCurrency: string | null;
151
- salaryTimeframe: string | null;
152
- isFeatured: boolean;
153
- locationLabel: string | null;
154
- company: {
155
- slug: string;
156
- name: string;
157
- logoUrl: string | null;
158
- } | null;
159
- categories: Array<{
160
- slug: string;
161
- name: string;
162
- }>;
163
- skills: Array<{
164
- slug: string;
165
- name: string;
166
- }>;
167
- links: {
168
- public: string | null;
169
- };
170
- /**
171
- * Long-form description (HTML), or `null`. Present ONLY when the list/search
172
- * was called with `fields: '+description'` (the RSS feed's sparse-fieldset
173
- * opt-in); `undefined`/absent on the default slim card.
174
- */
175
- description?: string | null;
176
- }
1904
+ type PublicJob = Schemas['PublicJob'];
1905
+ type PublicJobCard = Schemas['PublicJobCard'];
1906
+ type JobCompany = Schemas['JobCompany'];
1907
+ type OfficeLocation = Schemas['JobOfficeLocation'];
1908
+ type RemoteOption = NonNullable<PublicJob['remoteOption']>;
1909
+ type EmploymentType = NonNullable<PublicJob['employmentType']>;
1910
+ type Seniority = NonNullable<PublicJob['seniority']>;
1911
+ type EducationRequirement = PublicJob['educationRequirements'][number];
1912
+ type RemotePermit = PublicJob['remotePermits'][number];
1913
+ type RemoteTimezone = PublicJob['remoteTimezones'][number];
177
1914
  /** Derived category/skill suggestion on the jobs browse list (ADR-0037 §8). */
178
1915
  interface RelatedSearch {
179
1916
  type: 'category' | 'skill';
@@ -193,11 +1930,11 @@ type JobsListQuery = {
193
1930
  limit?: number;
194
1931
  /** Storefront page offset; takes precedence over `cursor`. `offset + limit` ≤ 10,000. */
195
1932
  offset?: number;
196
- /** Single or repeated (up to 10) — repeated params are OR-matched. */
197
- companyId?: string | string[];
198
- remoteOption?: RemoteOption | RemoteOption[];
199
- employmentType?: EmploymentType | EmploymentType[];
200
- seniority?: Seniority | Seniority[];
1933
+ /** Repeated param (up to 10) — OR-matched. Repeat `companyId` per value. */
1934
+ companyId?: string[];
1935
+ remoteOption?: RemoteOption[];
1936
+ employmentType?: EmploymentType[];
1937
+ seniority?: Seniority[];
201
1938
  /** Place slug for a geo radius search; unresolvable slugs are ignored. */
202
1939
  location?: string;
203
1940
  /** Radius in km around `location` (10–250; default 50). */
@@ -213,31 +1950,7 @@ type JobsSimilarQuery = {
213
1950
  /** How many similar jobs to return (1–20; default 5). */
214
1951
  limit?: number;
215
1952
  };
216
- interface JobsSearchBody {
217
- /** Free-text query, up to 200 characters. */
218
- query?: string;
219
- filters?: {
220
- /** Up to 10 values each. */
221
- companyId?: string[];
222
- remoteOption?: RemoteOption[];
223
- employmentType?: EmploymentType[];
224
- seniority?: Seniority[];
225
- /** ISO 8601 datetime bounds. */
226
- publishedAt?: {
227
- gte?: string;
228
- lte?: string;
229
- };
230
- /** Place slug for a geo radius search. */
231
- location?: string;
232
- /** Radius in km around `location` (10–250; default 50). */
233
- radius?: number;
234
- };
235
- cursor?: string;
236
- /** 1–100. */
237
- limit?: number;
238
- /** Storefront page offset; takes precedence over `cursor`. */
239
- offset?: number;
240
- }
1953
+ type JobsSearchBody = Schemas['PublicSearchJobsBody'];
241
1954
 
242
1955
  type Awaitable<T> = T | Promise<T>;
243
1956
  /**
@@ -305,71 +2018,6 @@ declare class BoardClient {
305
2018
  fetch<T>(path: string, init?: FetchOptions): Promise<T>;
306
2019
  }
307
2020
 
308
- interface PublicBoardFeatures {
309
- jobAlerts: boolean;
310
- candidates: boolean;
311
- employers: boolean;
312
- blog: boolean;
313
- talentDirectory: boolean;
314
- registrationWall: boolean;
315
- passwordProtected: boolean;
316
- publicJobSubmission: boolean;
317
- candidatePaywall: boolean;
318
- }
319
- interface PublicBoardAnalytics {
320
- ga4MeasurementId: string | null;
321
- gtmId: string | null;
322
- metaPixelId: string | null;
323
- linkedInPartnerId: string | null;
324
- cookieConsentRequired: boolean;
325
- }
326
- interface PublicBoardTheme {
327
- mode: string;
328
- schemeId: string;
329
- typography: {
330
- fontSans: string;
331
- fontHeading?: string | null;
332
- };
333
- colors: Record<string, unknown>;
334
- }
335
- interface PublicBoard {
336
- object: 'public_board';
337
- /** Immutable board identifier (`boards_…`, ADR-0032). */
338
- id: string;
339
- /** Mutable canonical slug. */
340
- slug: string;
341
- name: string;
342
- language: string;
343
- logoUrl: string | null;
344
- primaryDomain: string | null;
345
- /** Whitelabel toggle (default `true`) — render the "Powered by Cavuno" badge unless `false`. */
346
- showCavunoBranding: boolean;
347
- features: PublicBoardFeatures;
348
- analytics: PublicBoardAnalytics;
349
- theme: PublicBoardTheme | null;
350
- }
351
-
352
- /**
353
- * The public SEO-infra payload (`board.seo()`). The four values a headless
354
- * frontend rebuilds `robots.txt` / `ads.txt` / `indexnow-key.txt` (+ the Google
355
- * site-verification `<meta>`) from — byte-identically to the hosted board.
356
- */
357
- interface BoardSeo {
358
- object: 'board_seo';
359
- /** Verbatim `ads.txt` content, or `null` when not configured. */
360
- adsTxt: string | null;
361
- /** IndexNow key-file content, or `null` when not configured. */
362
- indexNowKey: string | null;
363
- /** Google site-verification token for the `<meta>` tag, or `null`. */
364
- googleSiteVerification: string | null;
365
- /**
366
- * The board's canonical base URL (honours a configured custom domain). Build
367
- * the `robots.txt` `Sitemap:` line (`${canonicalBase}/sitemap.xml`) and
368
- * canonical links from it — NOT the request origin.
369
- */
370
- canonicalBase: string;
371
- }
372
-
373
2021
  /**
374
2022
  * Error raised for every non-2xx Board API response.
375
2023
  *
@@ -423,63 +2071,31 @@ declare function isConflict(e: unknown): e is BoardApiError;
423
2071
  * constant because the package is platform-neutral and cannot read
424
2072
  * package.json at runtime.
425
2073
  */
426
- declare const SDK_VERSION = "1.3.0";
2074
+ declare const SDK_VERSION = "1.5.0";
427
2075
 
428
- interface BoardUser {
429
- id: string;
430
- object: 'board_user';
431
- role: 'candidate' | 'employer';
432
- email: string;
433
- displayName: string | null;
434
- emailVerified: boolean;
435
- }
436
- /**
437
- * Bearer pair returned by register/login/refresh. `expiresAt` is the
438
- * ACCESS token expiry in epoch ms; the refresh token's own 30-day TTL
439
- * is intentionally not exposed.
440
- */
441
- interface BoardAuthSession {
442
- object: 'board_auth_session';
443
- accessToken: string;
444
- refreshToken: string;
445
- expiresAt: number;
446
- boardUser: BoardUser;
447
- }
448
- interface RegisterBody {
449
- role: 'candidate' | 'employer';
450
- /** Only `emailpass` is supported. */
451
- method: 'emailpass';
452
- email: string;
453
- password: string;
454
- displayName: string;
455
- }
456
- interface LoginBody {
457
- email: string;
458
- password: string;
459
- }
460
- interface RefreshBody {
461
- refreshToken: string;
462
- }
463
- interface LogoutBody {
464
- refreshToken: string;
465
- }
466
- interface VerifyEmailBody {
467
- token: string;
468
- }
469
- interface ForgotPasswordBody {
470
- email: string;
471
- }
472
- interface ResetPasswordBody {
473
- token: string;
474
- password: string;
475
- }
2076
+ type BoardUser = Schemas['BoardUser'];
2077
+ type BoardAuthSession = Schemas['BoardAuthSession'];
2078
+ type RegisterBody = Schemas['BoardAuthRegisterBody'];
2079
+ type LoginBody = Schemas['BoardAuthLoginBody'];
2080
+ type RefreshBody = Schemas['BoardAuthRefreshBody'];
2081
+ type LogoutBody = Schemas['BoardAuthLogoutBody'];
2082
+ type VerifyEmailBody = Schemas['BoardAuthVerifyEmailBody'];
2083
+ type ForgotPasswordBody = Schemas['BoardAuthForgotPasswordBody'];
2084
+ type ResetPasswordBody = Schemas['BoardAuthResetPasswordBody'];
2085
+
2086
+ type PublicBoard = Schemas['PublicBoardContext'];
2087
+ type PublicBoardFeatures = PublicBoard['features'];
2088
+ type PublicBoardAnalytics = PublicBoard['analytics'];
2089
+ type PublicBoardTheme = NonNullable<PublicBoard['theme']>;
476
2090
 
477
2091
  /**
478
- * Query for `board.embed.jobs()` — the embeddable, UNGATED jobs widget. Mirrors
479
- * the browse list's facets + geo, plus a free-text `q` keyword (the widget is
480
- * searchable). Deliberately has NO `category`/`skill` programmatic seeding and
481
- * NO `fields` sparse fieldset — the embed widget exposes none of those.
2092
+ * The public SEO-infra payload (`board.seo()`) — the values a headless
2093
+ * frontend rebuilds `robots.txt` / `ads.txt` / `indexnow-key.txt` (+ the
2094
+ * Google site-verification `<meta>` + favicons/web-manifest) from,
2095
+ * byte-identically to the hosted board.
482
2096
  */
2097
+ type BoardSeo = Schemas['BoardSeo'];
2098
+
483
2099
  type EmbedJobsQuery = {
484
2100
  /** Free-text search query, up to 200 characters. */
485
2101
  q?: string;
@@ -488,11 +2104,11 @@ type EmbedJobsQuery = {
488
2104
  limit?: number;
489
2105
  /** Storefront page offset; takes precedence over `cursor`. `offset + limit` ≤ 10,000. */
490
2106
  offset?: number;
491
- /** Single or repeated (up to 10) — repeated params are OR-matched. */
492
- companyId?: string | string[];
493
- remoteOption?: RemoteOption | RemoteOption[];
494
- employmentType?: EmploymentType | EmploymentType[];
495
- seniority?: Seniority | Seniority[];
2107
+ /** Repeated param (up to 10) — OR-matched. Repeat `companyId` per value. */
2108
+ companyId?: string[];
2109
+ remoteOption?: RemoteOption[];
2110
+ employmentType?: EmploymentType[];
2111
+ seniority?: Seniority[];
496
2112
  /** Place slug for a geo radius search; unresolvable slugs are ignored. */
497
2113
  location?: string;
498
2114
  /** Radius in km around `location` (10–250; default 50). */
@@ -500,92 +2116,53 @@ type EmbedJobsQuery = {
500
2116
  };
501
2117
 
502
2118
  /**
503
- * The board-access grant returned by `password.verify()`. Send `token` as the
504
- * `X-Board-Access` header on content reads to pass a board's password wall
505
- * (the SDK does this automatically once the grant is stored).
2119
+ * The board-access grant returned by `password.verify()`. Send `token` as
2120
+ * the `X-Board-Access` header on content reads to pass a board's password
2121
+ * wall (the SDK does this automatically once the grant is stored).
506
2122
  */
507
- interface BoardAccessGrant {
508
- object: 'board_access_grant';
509
- token: string;
510
- }
2123
+ type BoardAccessGrant = Schemas['BoardAccessGrant'];
511
2124
 
512
2125
  /**
513
2126
  * The result of resolving a path against the board's configured redirects
514
- * (`board.redirects.resolve()`). A headless frontend 308s to `target`, or 404s
515
- * when it's `null`.
2127
+ * (`board.redirects.resolve()`). A headless frontend 308s to `target`, or
2128
+ * 404s when it's `null`.
516
2129
  */
517
- interface RedirectResolution {
518
- object: 'redirect_resolution';
519
- /** The path that was resolved. */
520
- path: string;
521
- /** The redirect target (board-relative), or `null` when no redirect matches. */
522
- target: string | null;
523
- }
2130
+ type RedirectResolution = Schemas['RedirectResolution'];
524
2131
 
525
- /** Author shape embedded on posts (no `object` discriminator). */
526
- interface BlogAuthorEmbed {
527
- id: string;
528
- name: string;
529
- slug: string;
530
- bio: string | null;
531
- avatarUrl: string | null;
532
- websiteUrl: string | null;
533
- twitterUrl: string | null;
534
- linkedinUrl: string | null;
535
- githubUrl: string | null;
536
- }
537
- /** Tag shape embedded on posts (no `object` discriminator). */
538
- interface BlogTagEmbed {
539
- id: string;
540
- name: string;
541
- slug: string;
542
- description: string | null;
543
- }
544
- interface PublicBlogAuthor extends BlogAuthorEmbed {
545
- object: 'public_blog_author';
546
- }
547
- interface PublicBlogTag extends BlogTagEmbed {
548
- object: 'public_blog_tag';
2132
+ /**
2133
+ * A board legal/about page (ADR-0039 transitional portable-prose field). The
2134
+ * API serves owner-authored prose as portable HTML; the starter authors the
2135
+ * layout + JSON-LD. Impressum additionally carries structured legal-entity
2136
+ * facts and is gated by the board's `impressumEnabled` flag (404 when off).
2137
+ */
2138
+ type LegalPageType = 'terms-of-service' | 'privacy-policy' | 'cookie-policy' | 'about' | 'impressum';
2139
+ interface LegalEntity {
2140
+ legalName: string | null;
2141
+ address: string | null;
549
2142
  }
550
- interface PublicBlogPostSummary {
551
- id: string;
552
- object: 'public_blog_post';
2143
+ interface PublicLegalPage {
2144
+ object: 'legal_page';
2145
+ type: string;
2146
+ /** Page heading (H1), with `{{board_name}}` resolved. */
553
2147
  title: string;
554
- slug: string;
555
- featured: boolean;
556
- coverUrl: string | null;
557
- /** Alt text for `coverUrl` (the cover/feature image). */
558
- featureImageAlt: string | null;
559
- customExcerpt: string | null;
560
- readingTimeMin: number | null;
561
- publishedAt: string | null;
562
- /** A custom canonical URL override for this post, if set. */
563
- canonicalUrl: string | null;
564
- createdAt: string;
565
- authors: BlogAuthorEmbed[];
566
- tags: BlogTagEmbed[];
2148
+ /** Owner-authored prose as portable HTML; `''` when the page has no body. */
2149
+ content: string;
2150
+ contentFormat: 'html';
2151
+ /** Structured impressum facts; `null` for non-impressum pages. */
2152
+ legalEntity: LegalEntity | null;
567
2153
  }
2154
+
2155
+ /** Author shape embedded on posts (no `object` discriminator). */
2156
+ type BlogAuthorEmbed = Schemas['PublicBlogAuthorEmbed'];
2157
+ /** Tag shape embedded on posts (no `object` discriminator). */
2158
+ type BlogTagEmbed = Schemas['PublicBlogTagEmbed'];
2159
+ type PublicBlogAuthor = Schemas['PublicBlogAuthor'];
2160
+ type PublicBlogTag = Schemas['PublicBlogTag'];
2161
+ type PublicBlogPostSummary = Schemas['PublicBlogPostSummary'];
568
2162
  /** Detail shape — `html` appears on the single read only, never on summaries. */
569
- interface PublicBlogPost extends PublicBlogPostSummary {
570
- html: string | null;
571
- ogImageUrl: string | null;
572
- featureImageCaption: string | null;
573
- seoTitle: string | null;
574
- seoDescription: string | null;
575
- /**
576
- * Slug-history resolution. When the requested slug is a renamed post's OLD
577
- * slug, `redirected` is `true` and `newSlug` is the post's current slug —
578
- * issue a 308 to it. Otherwise `redirected` is `false` and `newSlug` is null.
579
- */
580
- redirected: boolean;
581
- newSlug: string | null;
582
- }
2163
+ type PublicBlogPost = Schemas['PublicBlogPost'];
583
2164
  /** Previous (older) + next (newer) posts for the detail prev/next nav. */
584
- interface PublicBlogAdjacentPosts {
585
- object: 'blog_adjacent_posts';
586
- previous: PublicBlogPostSummary | null;
587
- next: PublicBlogPostSummary | null;
588
- }
2165
+ type PublicBlogAdjacentPosts = Schemas['PublicBlogAdjacentPosts'];
589
2166
  type BlogPostsListQuery = {
590
2167
  cursor?: string;
591
2168
  /** 1–100. */
@@ -599,28 +2176,9 @@ type BlogSimilarQuery = {
599
2176
  /** 1–20; default 6. */
600
2177
  limit?: number;
601
2178
  };
602
- interface BlogSearchBody {
603
- /** Free-text query, 1–200 characters. Required. */
604
- query: string;
605
- cursor?: string | null;
606
- /** 1–50. */
607
- limit?: number;
608
- }
2179
+ type BlogSearchBody = Schemas['PublicBlogSearchBody'];
609
2180
 
610
- interface PublicCompany {
611
- id: string;
612
- object: 'public_company';
613
- name: string;
614
- slug: string;
615
- website: string | null;
616
- logoUrl: string | null;
617
- description: string | null;
618
- jobCount: number;
619
- publishedJobCount: number;
620
- links: {
621
- public: string | null;
622
- };
623
- }
2181
+ type PublicCompany = Schemas['CompanyPublic'];
624
2182
  type CompaniesListQuery = {
625
2183
  cursor?: string;
626
2184
  /** 1–100. */
@@ -631,34 +2189,25 @@ type CompanyJobsListQuery = {
631
2189
  /** 1–100. */
632
2190
  limit?: number;
633
2191
  };
634
- interface CompaniesSearchBody {
635
- /** Free-text query, up to 200 characters. */
636
- query?: string;
637
- cursor?: string;
638
- /** 1–100. */
2192
+ type CompanySimilarQuery = {
2193
+ /** 1–20, default 6. */
639
2194
  limit?: number;
640
- }
2195
+ };
2196
+ type CompanyMarket = Schemas['CompanyMarket'];
2197
+ type CompanyMarketsListQuery = {
2198
+ /** 1–200, default 100 (a top-by-company-count preview). */
2199
+ limit?: number;
2200
+ search?: string;
2201
+ };
2202
+ type CompaniesSearchBody = Schemas['PublicCompaniesSearchBody'];
641
2203
 
642
- /**
643
- * The embedded `job` is the SAME `public_job` shape the anonymous jobs
644
- * list emits — saved rows and search rows render with one component.
645
- */
646
- interface SavedJob {
647
- id: string;
648
- object: 'saved_job';
649
- jobId: string;
650
- /** ISO 8601. */
651
- savedAt: string;
652
- job: PublicJob;
653
- }
2204
+ type SavedJob = Schemas['SavedJob'];
654
2205
  type SavedJobsListQuery = {
655
2206
  cursor?: string;
656
2207
  /** 1–100. */
657
2208
  limit?: number;
658
2209
  };
659
- interface SaveJobBody {
660
- jobId: string;
661
- }
2210
+ type SaveJobBody = Schemas['SaveJobBody'];
662
2211
 
663
2212
  type JobAlertFrequency = 'daily' | 'weekly';
664
2213
  type JobAlertRemoteOption = 'on_site' | 'hybrid' | 'remote';
@@ -689,55 +2238,15 @@ type JobAlertSubscribeInput = {
689
2238
  jobSlug?: string;
690
2239
  };
691
2240
  };
692
- interface JobAlertSubscription {
693
- object: 'job_alert_subscription';
694
- status: 'created' | 'duplicate';
695
- requiresConfirmation: boolean;
696
- confirmed: boolean;
697
- }
698
- interface JobAlertConfirmation {
699
- object: 'job_alert_confirmation';
700
- status: 'confirmed' | 'already_confirmed' | 'expired' | 'not_found';
701
- }
702
- interface JobAlertResendResult {
703
- object: 'job_alert_confirmation_resend';
704
- status: 'sent' | 'not_found' | 'already_confirmed' | 'throttled' | 'send_failed';
705
- }
706
- interface JobAlertManageResult {
707
- object: 'job_alert_manage_result';
708
- success: boolean;
709
- }
710
- /**
711
- * The stored filter criteria surfaced on the manage page (a serializable subset
712
- * of the internal filter object — the fields a consumer renders). `jobFunctions`,
713
- * `placeIds` and `remoteOptions` are the dimensions the digest actually matches on.
714
- */
715
- interface JobAlertStoredFilters {
716
- jobFunctions?: string[];
717
- seniorityLevels?: string[];
718
- remoteOptions?: string[];
719
- placeIds?: string[];
720
- salaryMin?: number | null;
721
- salaryMax?: number | null;
722
- salaryCurrency?: string | null;
723
- frequency?: string;
724
- }
725
- interface JobAlertPreference {
726
- id: string;
727
- label: string | null;
728
- frequency: string;
729
- isActive: boolean;
730
- filters: JobAlertStoredFilters;
731
- /** Per-preference HMAC token for `updatePreference`/`deletePreference`. */
732
- manageToken: string;
733
- }
734
- interface JobAlertManageState {
735
- object: 'job_alert_manage_state';
736
- email: string;
737
- confirmed: boolean;
738
- unsubscribed: boolean;
739
- preferences: JobAlertPreference[];
740
- }
2241
+ type JobAlertSubscription = Schemas['PublicJobAlertSubscription'];
2242
+ type JobAlertConfirmation = Schemas['PublicJobAlertConfirmation'];
2243
+ type JobAlertResendResult = Schemas['PublicJobAlertResend'];
2244
+ type JobAlertManageResult = Schemas['PublicJobAlertManageResult'];
2245
+ type JobAlertManageState = Schemas['PublicJobAlertManageState'];
2246
+ /** One stored alert preference on the manage page. */
2247
+ type JobAlertPreference = JobAlertManageState['preferences'][number];
2248
+ /** The stored filter criteria surfaced on a manage-page preference. */
2249
+ type JobAlertStoredFilters = JobAlertPreference['filters'];
741
2250
  /** Query for `jobAlerts.manage` — the HMAC manage token from the digest email. */
742
2251
  type JobAlertManageQuery = {
743
2252
  subscription: string;
@@ -763,36 +2272,13 @@ type JobAlertDeletePreferenceInput = {
763
2272
  token: string;
764
2273
  };
765
2274
 
766
- interface TaxonomyGeo {
767
- lat: number | null;
768
- lng: number | null;
769
- countryCode: string | null;
770
- regionCode: string | null;
771
- region: string | null;
772
- city: string | null;
773
- locality: string | null;
774
- placeType: string | null;
775
- }
776
- /**
777
- * Page-meta for a resolved taxonomy slug. `sourceSlug` is the immutable
778
- * English search key; `canonicalSlug` is the board-language URL; `redirectTo`
779
- * is the canonical slug to 308 to when the inbound slug isn't canonical (the
780
- * host app emits the redirect — the SDK never navigates). `geo` is set for
781
- * place resolutions only.
782
- */
783
- interface TaxonomyResolution {
784
- object: 'taxonomy_resolution';
785
- type: 'category' | 'skill' | 'place';
786
- sourceSlug: string;
787
- canonicalSlug: string;
788
- displayName: string;
789
- redirectTo: string | null;
790
- geo: TaxonomyGeo | null;
791
- }
2275
+ type TaxonomyGeo = Schemas['TaxonomyGeo'];
2276
+ type TaxonomyResolution = Schemas['PublicTaxonomyResolution'];
2277
+ type PublicPlace = Schemas['PublicPlace'];
792
2278
  /**
793
- * Query for `taxonomy.places.list()`. Omit it (or `q`) for the full locations
794
- * directory; pass `q` (≥2 chars) for location autocomplete — the top name
795
- * matches ranked, what a location search field renders.
2279
+ * Query for `taxonomy.places.list()`. Omit it (or `q`) for the full
2280
+ * locations directory; pass `q` (≥2 chars) for location autocomplete — the
2281
+ * top name matches ranked, what a location search field renders.
796
2282
  */
797
2283
  type PlacesListQuery = {
798
2284
  /** Location autocomplete query; ≥2 chars → top name matches, under 2 → empty. */
@@ -800,26 +2286,6 @@ type PlacesListQuery = {
800
2286
  /** Max autocomplete results when `q` is given (1–50; default 10). */
801
2287
  limit?: number;
802
2288
  };
803
- /**
804
- * A place in the board's locations directory (`taxonomy.places.list()` →
805
- * `GET /places`), the data the `/jobs/locations/` index renders. `jobCount` is
806
- * subtree-summed (a parent counts its descendants); `id`/`parentId` carry the
807
- * hierarchy so consumers rebuild the same nested tree the hosted index shows.
808
- */
809
- interface PublicPlace {
810
- object: 'place';
811
- /** Stable place identity (locations-tree edge endpoint). */
812
- id: string;
813
- /** Parent place's `id`; `null` for a root place. */
814
- parentId: string | null;
815
- /** Public slug (links to `/jobs/locations/:slug`); `null` if unslugged. */
816
- slug: string | null;
817
- name: string;
818
- placeType: string;
819
- countryCode: string | null;
820
- regionCode: string | null;
821
- jobCount: number;
822
- }
823
2289
 
824
2290
  interface CreateBoardClientOptions {
825
2291
  baseUrl: string;
@@ -863,7 +2329,51 @@ declare function createBoardClient(options: CreateBoardClientOptions): {
863
2329
  * @example
864
2330
  * const { name, theme } = await board.context();
865
2331
  */
866
- context(options?: FetchOptions): Promise<PublicBoard>;
2332
+ context(options?: FetchOptions): Promise<{
2333
+ object: "public_board";
2334
+ id: string;
2335
+ slug: string;
2336
+ name: string;
2337
+ language: string;
2338
+ logoUrl: string | null;
2339
+ primaryDomain: string | null;
2340
+ showCavunoBranding: boolean;
2341
+ features: {
2342
+ jobAlerts: boolean;
2343
+ candidates: boolean;
2344
+ employers: boolean;
2345
+ blog: boolean;
2346
+ talentDirectory: boolean;
2347
+ registrationWall: boolean;
2348
+ passwordProtected: boolean;
2349
+ publicJobSubmission: boolean;
2350
+ candidatePaywall: boolean;
2351
+ impressum: boolean;
2352
+ };
2353
+ analytics: {
2354
+ ga4MeasurementId: string | null;
2355
+ gtmId: string | null;
2356
+ metaPixelId: string | null;
2357
+ linkedInPartnerId: string | null;
2358
+ cookieConsentRequired: boolean;
2359
+ };
2360
+ theme: {
2361
+ mode: string;
2362
+ schemeId: string;
2363
+ typography: {
2364
+ fontSans: string;
2365
+ fontHeading?: string | null;
2366
+ };
2367
+ colors: {
2368
+ light: {
2369
+ [key: string]: unknown;
2370
+ };
2371
+ dark: {
2372
+ [key: string]: unknown;
2373
+ };
2374
+ };
2375
+ } | null;
2376
+ }>;
867
2377
  /**
868
2378
  * Board SEO infra — `ads.txt`, IndexNow key, Google site-verification, and
869
2379
  * the canonical base URL. Rebuild `robots.txt` / `ads.txt` /
@@ -872,53 +2382,391 @@ declare function createBoardClient(options: CreateBoardClientOptions): {
872
2382
  * @example
873
2383
  * const { adsTxt, canonicalBase } = await board.seo();
874
2384
  */
875
- seo(options?: FetchOptions): Promise<BoardSeo>;
2385
+ seo(options?: FetchOptions): Promise<{
2386
+ object: "board_seo";
2387
+ adsTxt: string | null;
2388
+ indexNowKey: string | null;
2389
+ googleSiteVerification: string | null;
2390
+ canonicalBase: string;
2391
+ icons: {
2392
+ ico: string | null;
2393
+ svg: string | null;
2394
+ appleTouch: string | null;
2395
+ icon192: string | null;
2396
+ icon512: string | null;
2397
+ iconMaskable512: string | null;
2398
+ };
2399
+ manifest: {
2400
+ name: string;
2401
+ themeColor: string;
2402
+ };
2403
+ }>;
876
2404
  jobs: {
877
2405
  list(query?: JobsListQuery, options?: FetchOptions): Promise<JobCardListEnvelope>;
878
- retrieve(jobSlug: string, query?: Record<string, never>, options?: FetchOptions): Promise<PublicJob>;
2406
+ retrieve(jobSlug: string, query?: Record<string, never>, options?: FetchOptions): Promise<{
2407
+ id: string;
2408
+ object: "public_job";
2409
+ title: string;
2410
+ slug: string | null;
2411
+ status: "draft" | "published" | "expired" | "archived";
2412
+ companyId: string | null;
2413
+ employmentType: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other" | null;
2414
+ remoteOption: "on_site" | "hybrid" | "remote" | null;
2415
+ seniority: "entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive" | null;
2416
+ salaryMin: number | null;
2417
+ salaryMax: number | null;
2418
+ salaryCurrency: string | null;
2419
+ salaryTimeframe: "per_year" | "per_month" | "per_week" | "per_day" | "per_hour" | null;
2420
+ isFeatured: boolean;
2421
+ publishedAt: string | null;
2422
+ expiresAt: string | null;
2423
+ createdAt: string;
2424
+ updatedAt: string;
2425
+ links: components["schemas"]["PublicJobLinks"];
2426
+ description: string | null;
2427
+ applicationUrl: string | null;
2428
+ remotePermits: {
2429
+ type: string;
2430
+ value: string;
2431
+ }[];
2432
+ remoteWorldwide: boolean | null;
2433
+ remoteTimezones: {
2434
+ type: string;
2435
+ value: string;
2436
+ plusMinus?: number;
2437
+ }[];
2438
+ remoteAllowedTzOffsets: number[];
2439
+ remoteWorkPermitCountryCodes: string[];
2440
+ remoteWorkPermitSubdivisionCodes: string[];
2441
+ remoteSponsorship: "yes" | "no" | "unknown";
2442
+ educationRequirements: ("high_school" | "associate_degree" | "bachelor_degree" | "professional_certificate" | "postgraduate_degree" | "no_requirements")[];
2443
+ experienceMonths: number | null;
2444
+ experienceInPlaceOfEducation: boolean | null;
2445
+ inOfficePeriod: "per_week" | "per_month" | "per_year" | null;
2446
+ inOfficeFrequency: number | null;
2447
+ company: components["schemas"]["JobCompany"];
2448
+ officeLocations: components["schemas"]["JobOfficeLocation"][];
2449
+ categories: {
2450
+ slug: string;
2451
+ name: string;
2452
+ }[];
2453
+ skills: {
2454
+ slug: string;
2455
+ name: string;
2456
+ }[];
2457
+ placeHierarchy: {
2458
+ slug: string;
2459
+ name: string;
2460
+ }[];
2461
+ }>;
879
2462
  search(body: JobsSearchBody, query?: Record<string, never>, options?: FetchOptions): Promise<JobCardSearchEnvelope>;
880
- similar(jobSlug: string, query?: JobsSimilarQuery, options?: FetchOptions): Promise<ListEnvelope<PublicJobCard>>;
2463
+ similar(jobSlug: string, query?: JobsSimilarQuery, options?: FetchOptions): Promise<ListEnvelope<{
2464
+ id: string;
2465
+ object: "job_card";
2466
+ slug: string;
2467
+ title: string;
2468
+ publishedAt: string | null;
2469
+ employmentType: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other" | null;
2470
+ remoteOption: "on_site" | "hybrid" | "remote" | null;
2471
+ remoteLocationLabel: string | null;
2472
+ salaryMin: number | null;
2473
+ salaryMax: number | null;
2474
+ salaryCurrency: string | null;
2475
+ salaryTimeframe: string | null;
2476
+ isFeatured: boolean;
2477
+ locationLabel: string | null;
2478
+ company: {
2479
+ slug: string;
2480
+ name: string;
2481
+ logoUrl: string | null;
2482
+ } | null;
2483
+ categories: {
2484
+ slug: string;
2485
+ name: string;
2486
+ }[];
2487
+ skills: {
2488
+ slug: string;
2489
+ name: string;
2490
+ }[];
2491
+ links: {
2492
+ public: string | null;
2493
+ };
2494
+ description?: string | null;
2495
+ }>>;
881
2496
  };
882
2497
  embed: {
883
- jobs(query?: EmbedJobsQuery, options?: FetchOptions): Promise<ListEnvelope<PublicJobCard>>;
2498
+ jobs(query?: EmbedJobsQuery, options?: FetchOptions): Promise<ListEnvelope<{
2499
+ id: string;
2500
+ object: "job_card";
2501
+ slug: string;
2502
+ title: string;
2503
+ publishedAt: string | null;
2504
+ employmentType: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other" | null;
2505
+ remoteOption: "on_site" | "hybrid" | "remote" | null;
2506
+ remoteLocationLabel: string | null;
2507
+ salaryMin: number | null;
2508
+ salaryMax: number | null;
2509
+ salaryCurrency: string | null;
2510
+ salaryTimeframe: string | null;
2511
+ isFeatured: boolean;
2512
+ locationLabel: string | null;
2513
+ company: {
2514
+ slug: string;
2515
+ name: string;
2516
+ logoUrl: string | null;
2517
+ } | null;
2518
+ categories: {
2519
+ slug: string;
2520
+ name: string;
2521
+ }[];
2522
+ skills: {
2523
+ slug: string;
2524
+ name: string;
2525
+ }[];
2526
+ links: {
2527
+ public: string | null;
2528
+ };
2529
+ description?: string | null;
2530
+ }>>;
884
2531
  };
885
2532
  companies: {
886
- list(query?: CompaniesListQuery, options?: FetchOptions): Promise<ListEnvelope<PublicCompany>>;
887
- retrieve(companySlug: string, query?: Record<string, never>, options?: FetchOptions): Promise<PublicCompany>;
888
- search(body: CompaniesSearchBody, query?: Record<string, never>, options?: FetchOptions): Promise<SearchEnvelope<PublicCompany>>;
2533
+ list(query?: CompaniesListQuery, options?: FetchOptions): Promise<ListEnvelope<{
2534
+ id: string;
2535
+ object: "public_company";
2536
+ name: string;
2537
+ slug: string;
2538
+ website: string | null;
2539
+ logoUrl: string | null;
2540
+ description: string | null;
2541
+ jobCount: number;
2542
+ publishedJobCount: number;
2543
+ links: components["schemas"]["PublicCompanyLinks"];
2544
+ }>>;
2545
+ retrieve(companySlug: string, query?: Record<string, never>, options?: FetchOptions): Promise<{
2546
+ id: string;
2547
+ object: "public_company";
2548
+ name: string;
2549
+ slug: string;
2550
+ website: string | null;
2551
+ logoUrl: string | null;
2552
+ description: string | null;
2553
+ jobCount: number;
2554
+ publishedJobCount: number;
2555
+ links: components["schemas"]["PublicCompanyLinks"];
2556
+ }>;
2557
+ search(body: CompaniesSearchBody, query?: Record<string, never>, options?: FetchOptions): Promise<SearchEnvelope<{
2558
+ id: string;
2559
+ object: "public_company";
2560
+ name: string;
2561
+ slug: string;
2562
+ website: string | null;
2563
+ logoUrl: string | null;
2564
+ description: string | null;
2565
+ jobCount: number;
2566
+ publishedJobCount: number;
2567
+ links: components["schemas"]["PublicCompanyLinks"];
2568
+ }>>;
889
2569
  listJobs(companySlug: string, query?: CompanyJobsListQuery, options?: FetchOptions): Promise<JobCardListEnvelope>;
2570
+ similar(companySlug: string, query?: CompanySimilarQuery, options?: FetchOptions): Promise<ListEnvelope<{
2571
+ id: string;
2572
+ object: "public_company";
2573
+ name: string;
2574
+ slug: string;
2575
+ website: string | null;
2576
+ logoUrl: string | null;
2577
+ description: string | null;
2578
+ jobCount: number;
2579
+ publishedJobCount: number;
2580
+ links: components["schemas"]["PublicCompanyLinks"];
2581
+ }>>;
2582
+ markets(query?: CompanyMarketsListQuery, options?: FetchOptions): Promise<ListEnvelope<{
2583
+ object: "company_market";
2584
+ slug: string;
2585
+ name: string;
2586
+ companyCount: number;
2587
+ }>>;
890
2588
  };
891
2589
  blog: {
892
2590
  posts: {
893
- list(query?: BlogPostsListQuery, options?: FetchOptions): Promise<ListEnvelope<PublicBlogPostSummary>>;
894
- retrieve(postSlug: string, query?: Record<string, never>, options?: FetchOptions): Promise<PublicBlogPost>;
895
- adjacent(postSlug: string, options?: FetchOptions): Promise<PublicBlogAdjacentPosts>;
896
- similar(postSlug: string, query?: BlogSimilarQuery, options?: FetchOptions): Promise<ListEnvelope<PublicBlogPostSummary>>;
2591
+ list(query?: BlogPostsListQuery, options?: FetchOptions): Promise<ListEnvelope<{
2592
+ id: string;
2593
+ object: "public_blog_post";
2594
+ title: string;
2595
+ slug: string;
2596
+ featured: boolean;
2597
+ coverUrl: string | null;
2598
+ featureImageAlt: string | null;
2599
+ customExcerpt: string | null;
2600
+ readingTimeMin: number | null;
2601
+ publishedAt: string | null;
2602
+ canonicalUrl: string | null;
2603
+ createdAt: string;
2604
+ authors: components["schemas"]["PublicBlogAuthorEmbed"][];
2605
+ tags: components["schemas"]["PublicBlogTagEmbed"][];
2606
+ }>>;
2607
+ retrieve(postSlug: string, query?: Record<string, never>, options?: FetchOptions): Promise<{
2608
+ id: string;
2609
+ object: "public_blog_post";
2610
+ title: string;
2611
+ slug: string;
2612
+ featured: boolean;
2613
+ coverUrl: string | null;
2614
+ featureImageAlt: string | null;
2615
+ customExcerpt: string | null;
2616
+ readingTimeMin: number | null;
2617
+ publishedAt: string | null;
2618
+ canonicalUrl: string | null;
2619
+ createdAt: string;
2620
+ authors: components["schemas"]["PublicBlogAuthorEmbed"][];
2621
+ tags: components["schemas"]["PublicBlogTagEmbed"][];
2622
+ } & {
2623
+ html: string | null;
2624
+ ogImageUrl: string | null;
2625
+ featureImageCaption: string | null;
2626
+ seoTitle: string | null;
2627
+ seoDescription: string | null;
2628
+ redirected: boolean;
2629
+ newSlug: string | null;
2630
+ }>;
2631
+ adjacent(postSlug: string, options?: FetchOptions): Promise<{
2632
+ object: "blog_adjacent_posts";
2633
+ previous: components["schemas"]["PublicBlogPostSummary"] & unknown;
2634
+ next: components["schemas"]["PublicBlogPostSummary"] & unknown;
2635
+ }>;
2636
+ similar(postSlug: string, query?: BlogSimilarQuery, options?: FetchOptions): Promise<ListEnvelope<{
2637
+ id: string;
2638
+ object: "public_blog_post";
2639
+ title: string;
2640
+ slug: string;
2641
+ featured: boolean;
2642
+ coverUrl: string | null;
2643
+ featureImageAlt: string | null;
2644
+ customExcerpt: string | null;
2645
+ readingTimeMin: number | null;
2646
+ publishedAt: string | null;
2647
+ canonicalUrl: string | null;
2648
+ createdAt: string;
2649
+ authors: components["schemas"]["PublicBlogAuthorEmbed"][];
2650
+ tags: components["schemas"]["PublicBlogTagEmbed"][];
2651
+ }>>;
897
2652
  };
898
2653
  tags: {
899
- list(query?: Record<string, never>, options?: FetchOptions): Promise<ListEnvelope<PublicBlogTag>>;
900
- retrieve(tagSlug: string, query?: Record<string, never>, options?: FetchOptions): Promise<PublicBlogTag>;
2654
+ list(query?: Record<string, never>, options?: FetchOptions): Promise<ListEnvelope<{
2655
+ id: string;
2656
+ name: string;
2657
+ slug: string;
2658
+ description: string | null;
2659
+ } & {
2660
+ object: "public_blog_tag";
2661
+ }>>;
2662
+ retrieve(tagSlug: string, query?: Record<string, never>, options?: FetchOptions): Promise<{
2663
+ id: string;
2664
+ name: string;
2665
+ slug: string;
2666
+ description: string | null;
2667
+ } & {
2668
+ object: "public_blog_tag";
2669
+ }>;
901
2670
  };
902
2671
  authors: {
903
- list(query?: Record<string, never>, options?: FetchOptions): Promise<ListEnvelope<PublicBlogAuthor>>;
904
- retrieve(authorSlug: string, query?: Record<string, never>, options?: FetchOptions): Promise<PublicBlogAuthor>;
2672
+ list(query?: Record<string, never>, options?: FetchOptions): Promise<ListEnvelope<{
2673
+ id: string;
2674
+ name: string;
2675
+ slug: string;
2676
+ bio: string | null;
2677
+ avatarUrl: string | null;
2678
+ websiteUrl: string | null;
2679
+ twitterUrl: string | null;
2680
+ linkedinUrl: string | null;
2681
+ githubUrl: string | null;
2682
+ } & {
2683
+ object: "public_blog_author";
2684
+ }>>;
2685
+ retrieve(authorSlug: string, query?: Record<string, never>, options?: FetchOptions): Promise<{
2686
+ id: string;
2687
+ name: string;
2688
+ slug: string;
2689
+ bio: string | null;
2690
+ avatarUrl: string | null;
2691
+ websiteUrl: string | null;
2692
+ twitterUrl: string | null;
2693
+ linkedinUrl: string | null;
2694
+ githubUrl: string | null;
2695
+ } & {
2696
+ object: "public_blog_author";
2697
+ }>;
905
2698
  };
906
- search(body: BlogSearchBody, query?: Record<string, never>, options?: FetchOptions): Promise<SearchEnvelope<PublicBlogPostSummary>>;
2699
+ search(body: BlogSearchBody, query?: Record<string, never>, options?: FetchOptions): Promise<SearchEnvelope<{
2700
+ id: string;
2701
+ object: "public_blog_post";
2702
+ title: string;
2703
+ slug: string;
2704
+ featured: boolean;
2705
+ coverUrl: string | null;
2706
+ featureImageAlt: string | null;
2707
+ customExcerpt: string | null;
2708
+ readingTimeMin: number | null;
2709
+ publishedAt: string | null;
2710
+ canonicalUrl: string | null;
2711
+ createdAt: string;
2712
+ authors: components["schemas"]["PublicBlogAuthorEmbed"][];
2713
+ tags: components["schemas"]["PublicBlogTagEmbed"][];
2714
+ }>>;
2715
+ };
2716
+ legal: {
2717
+ retrieve(type: LegalPageType, options?: FetchOptions): Promise<PublicLegalPage>;
907
2718
  };
908
2719
  auth: {
909
- register(body: RegisterBody, options?: FetchOptions): Promise<BoardAuthSession>;
910
- login(body: LoginBody, options?: FetchOptions): Promise<BoardAuthSession>;
911
- refresh(body?: RefreshBody, options?: FetchOptions): Promise<BoardAuthSession>;
2720
+ register(body: RegisterBody, options?: FetchOptions): Promise<{
2721
+ object: "board_auth_session";
2722
+ accessToken: string;
2723
+ refreshToken: string;
2724
+ expiresAt: number;
2725
+ boardUser: components["schemas"]["BoardUser"];
2726
+ }>;
2727
+ login(body: LoginBody, options?: FetchOptions): Promise<{
2728
+ object: "board_auth_session";
2729
+ accessToken: string;
2730
+ refreshToken: string;
2731
+ expiresAt: number;
2732
+ boardUser: components["schemas"]["BoardUser"];
2733
+ }>;
2734
+ refresh(body?: RefreshBody, options?: FetchOptions): Promise<{
2735
+ object: "board_auth_session";
2736
+ accessToken: string;
2737
+ refreshToken: string;
2738
+ expiresAt: number;
2739
+ boardUser: components["schemas"]["BoardUser"];
2740
+ }>;
912
2741
  logout(body?: LogoutBody, options?: FetchOptions): Promise<void>;
913
2742
  verifyEmail(body: VerifyEmailBody, options?: FetchOptions): Promise<void>;
914
2743
  forgotPassword(body: ForgotPasswordBody, options?: FetchOptions): Promise<void>;
915
2744
  resetPassword(body: ResetPasswordBody, options?: FetchOptions): Promise<void>;
916
2745
  };
917
2746
  me: {
918
- retrieve(query?: Record<string, never>, options?: FetchOptions): Promise<BoardUser>;
2747
+ retrieve(query?: Record<string, never>, options?: FetchOptions): Promise<{
2748
+ id: string;
2749
+ object: "board_user";
2750
+ role: "candidate" | "employer";
2751
+ email: string;
2752
+ displayName: string | null;
2753
+ emailVerified: boolean;
2754
+ }>;
919
2755
  savedJobs: {
920
- list(query?: SavedJobsListQuery, options?: FetchOptions): Promise<ListEnvelope<SavedJob>>;
921
- save(body: SaveJobBody, query?: Record<string, never>, options?: FetchOptions): Promise<SavedJob>;
2756
+ list(query?: SavedJobsListQuery, options?: FetchOptions): Promise<ListEnvelope<{
2757
+ id: string;
2758
+ object: "saved_job";
2759
+ jobId: string;
2760
+ savedAt: string;
2761
+ job: components["schemas"]["PublicJob"];
2762
+ }>>;
2763
+ save(body: SaveJobBody, query?: Record<string, never>, options?: FetchOptions): Promise<{
2764
+ id: string;
2765
+ object: "saved_job";
2766
+ jobId: string;
2767
+ savedAt: string;
2768
+ job: components["schemas"]["PublicJob"];
2769
+ }>;
922
2770
  unsave(jobId: string, query?: Record<string, never>, options?: FetchOptions): Promise<void>;
923
2771
  };
924
2772
  };
@@ -927,34 +2775,110 @@ declare function createBoardClient(options: CreateBoardClientOptions): {
927
2775
  };
928
2776
  taxonomy: {
929
2777
  categories: {
930
- resolve(slug: string, options?: FetchOptions): Promise<TaxonomyResolution>;
2778
+ resolve(slug: string, options?: FetchOptions): Promise<{
2779
+ object: "taxonomy_resolution";
2780
+ type: "category" | "skill" | "place";
2781
+ sourceSlug: string;
2782
+ canonicalSlug: string;
2783
+ displayName: string;
2784
+ redirectTo: string | null;
2785
+ geo: components["schemas"]["TaxonomyGeo"];
2786
+ }>;
931
2787
  };
932
2788
  skills: {
933
- resolve(slug: string, options?: FetchOptions): Promise<TaxonomyResolution>;
2789
+ resolve(slug: string, options?: FetchOptions): Promise<{
2790
+ object: "taxonomy_resolution";
2791
+ type: "category" | "skill" | "place";
2792
+ sourceSlug: string;
2793
+ canonicalSlug: string;
2794
+ displayName: string;
2795
+ redirectTo: string | null;
2796
+ geo: components["schemas"]["TaxonomyGeo"];
2797
+ }>;
934
2798
  };
935
2799
  places: {
936
- list(query?: PlacesListQuery, options?: FetchOptions): Promise<ListEnvelope<PublicPlace>>;
937
- resolve(slug: string, options?: FetchOptions): Promise<TaxonomyResolution>;
2800
+ list(query?: PlacesListQuery, options?: FetchOptions): Promise<ListEnvelope<{
2801
+ object: "place";
2802
+ id: string;
2803
+ parentId: string | null;
2804
+ slug: string | null;
2805
+ name: string;
2806
+ placeType: string;
2807
+ countryCode: string | null;
2808
+ regionCode: string | null;
2809
+ jobCount: number;
2810
+ }>>;
2811
+ resolve(slug: string, options?: FetchOptions): Promise<{
2812
+ object: "taxonomy_resolution";
2813
+ type: "category" | "skill" | "place";
2814
+ sourceSlug: string;
2815
+ canonicalSlug: string;
2816
+ displayName: string;
2817
+ redirectTo: string | null;
2818
+ geo: components["schemas"]["TaxonomyGeo"];
2819
+ }>;
938
2820
  };
939
2821
  };
940
2822
  redirects: {
941
- resolve(path: string, options?: FetchOptions): Promise<RedirectResolution>;
2823
+ resolve(path: string, options?: FetchOptions): Promise<{
2824
+ object: "redirect_resolution";
2825
+ path: string;
2826
+ target: string | null;
2827
+ }>;
942
2828
  };
943
2829
  jobAlerts: {
944
- subscribe(input: JobAlertSubscribeInput, options?: FetchOptions): Promise<JobAlertSubscription>;
2830
+ subscribe(input: JobAlertSubscribeInput, options?: FetchOptions): Promise<{
2831
+ object: "job_alert_subscription";
2832
+ status: "created" | "duplicate";
2833
+ requiresConfirmation: boolean;
2834
+ confirmed: boolean;
2835
+ }>;
945
2836
  confirm(input: {
946
2837
  token: string;
947
- }, options?: FetchOptions): Promise<JobAlertConfirmation>;
2838
+ }, options?: FetchOptions): Promise<{
2839
+ object: "job_alert_confirmation";
2840
+ status: "confirmed" | "already_confirmed" | "expired" | "not_found";
2841
+ }>;
948
2842
  resendConfirmation(input: {
949
2843
  email: string;
950
- }, options?: FetchOptions): Promise<JobAlertResendResult>;
951
- manage(query: JobAlertManageQuery, options?: FetchOptions): Promise<JobAlertManageState>;
952
- unsubscribe(input: JobAlertManageTokenInput, options?: FetchOptions): Promise<JobAlertManageResult>;
953
- resubscribe(input: JobAlertManageTokenInput, options?: FetchOptions): Promise<JobAlertManageResult>;
954
- updatePreference(input: JobAlertUpdatePreferenceInput, options?: FetchOptions): Promise<JobAlertManageResult>;
955
- deletePreference(input: JobAlertDeletePreferenceInput, options?: FetchOptions): Promise<JobAlertManageResult>;
2844
+ }, options?: FetchOptions): Promise<{
2845
+ object: "job_alert_confirmation_resend";
2846
+ status: "sent" | "not_found" | "already_confirmed" | "throttled" | "send_failed";
2847
+ }>;
2848
+ manage(query: JobAlertManageQuery, options?: FetchOptions): Promise<{
2849
+ object: "job_alert_manage_state";
2850
+ email: string;
2851
+ confirmed: boolean;
2852
+ unsubscribed: boolean;
2853
+ preferences: {
2854
+ id: string;
2855
+ label: string | null;
2856
+ frequency: string;
2857
+ isActive: boolean;
2858
+ filters: {
2859
+ [key: string]: unknown;
2860
+ };
2861
+ manageToken: string;
2862
+ }[];
2863
+ }>;
2864
+ unsubscribe(input: JobAlertManageTokenInput, options?: FetchOptions): Promise<{
2865
+ object: "job_alert_manage_result";
2866
+ success: boolean;
2867
+ }>;
2868
+ resubscribe(input: JobAlertManageTokenInput, options?: FetchOptions): Promise<{
2869
+ object: "job_alert_manage_result";
2870
+ success: boolean;
2871
+ }>;
2872
+ updatePreference(input: JobAlertUpdatePreferenceInput, options?: FetchOptions): Promise<{
2873
+ object: "job_alert_manage_result";
2874
+ success: boolean;
2875
+ }>;
2876
+ deletePreference(input: JobAlertDeletePreferenceInput, options?: FetchOptions): Promise<{
2877
+ object: "job_alert_manage_result";
2878
+ success: boolean;
2879
+ }>;
956
2880
  };
957
2881
  };
958
2882
  type BoardSdk = ReturnType<typeof createBoardClient>;
959
2883
 
960
- export { ACCESS_TOKEN_KEY, type Awaitable, BOARD_ACCESS_GRANT_KEY, type BlogAuthorEmbed, type BlogPostsListQuery, type BlogSearchBody, type BlogSimilarQuery, type BlogTagEmbed, type BoardAccessGrant, BoardApiError, type BoardAuthSession, BoardClient, type BoardRequest, type BoardSdk, type BoardSeo, type BoardUser, type CompaniesListQuery, type CompaniesSearchBody, type CompanyJobsListQuery, type CreateBoardClientOptions, type CustomStorage, type EducationRequirement, type EmbedJobsQuery, type EmploymentType, type FetchOptions, type ForgotPasswordBody, type JobAlertConfirmation, type JobAlertDeletePreferenceInput, type JobAlertFiltersInput, type JobAlertFrequency, type JobAlertManageQuery, type JobAlertManageResult, type JobAlertManageState, type JobAlertManageTokenInput, type JobAlertPreference, type JobAlertRemoteOption, type JobAlertResendResult, type JobAlertStoredFilters, type JobAlertSubscribeInput, type JobAlertSubscription, type JobAlertUpdatePreferenceInput, type JobCardListEnvelope, type JobCardSearchEnvelope, type JobCompany, type JobsListQuery, type JobsSearchBody, type ListEnvelope, type Logger, type LoginBody, type LogoutBody, type OfficeLocation, type PlacesListQuery, type PublicBlogAdjacentPosts, type PublicBlogAuthor, type PublicBlogPost, type PublicBlogPostSummary, type PublicBlogTag, type PublicBoard, type PublicBoardAnalytics, type PublicBoardFeatures, type PublicBoardTheme, type PublicCompany, type PublicJob, type PublicJobCard, type PublicPlace, REFRESH_TOKEN_KEY, type RedirectResolution, type RefreshBody, type RegisterBody, type RelatedSearch, type RemoteOption, type RemotePermit, type RemoteTimezone, type ResetPasswordBody, SDK_VERSION, type SaveJobBody, type SavedJob, type SavedJobsListQuery, type SearchEnvelope, type Seniority, type StorageMode, type StorefrontPagination, type TaxonomyGeo, type TaxonomyResolution, type VerifyEmailBody, createBoardClient, isBoardApiError, isBoardPasswordRequired, isConflict, isForbidden, isNotFound, isRateLimited, isUnauthorized, isValidationError };
2884
+ export { ACCESS_TOKEN_KEY, type Awaitable, BOARD_ACCESS_GRANT_KEY, type BlogAuthorEmbed, type BlogPostsListQuery, type BlogSearchBody, type BlogSimilarQuery, type BlogTagEmbed, type BoardAccessGrant, BoardApiError, type BoardAuthSession, BoardClient, type BoardRequest, type BoardSdk, type BoardSeo, type BoardUser, type CompaniesListQuery, type CompaniesSearchBody, type CompanyJobsListQuery, type CompanyMarket, type CompanyMarketsListQuery, type CompanySimilarQuery, type CreateBoardClientOptions, type CustomStorage, type EducationRequirement, type EmbedJobsQuery, type EmploymentType, type FetchOptions, type ForgotPasswordBody, type JobAlertConfirmation, type JobAlertDeletePreferenceInput, type JobAlertFiltersInput, type JobAlertFrequency, type JobAlertManageQuery, type JobAlertManageResult, type JobAlertManageState, type JobAlertManageTokenInput, type JobAlertPreference, type JobAlertRemoteOption, type JobAlertResendResult, type JobAlertStoredFilters, type JobAlertSubscribeInput, type JobAlertSubscription, type JobAlertUpdatePreferenceInput, type JobCardListEnvelope, type JobCardSearchEnvelope, type JobCompany, type JobsListQuery, type JobsSearchBody, type LegalEntity, type LegalPageType, type ListEnvelope, type Logger, type LoginBody, type LogoutBody, type OfficeLocation, type PlacesListQuery, type PublicBlogAdjacentPosts, type PublicBlogAuthor, type PublicBlogPost, type PublicBlogPostSummary, type PublicBlogTag, type PublicBoard, type PublicBoardAnalytics, type PublicBoardFeatures, type PublicBoardTheme, type PublicCompany, type PublicJob, type PublicJobCard, type PublicLegalPage, type PublicPlace, REFRESH_TOKEN_KEY, type RedirectResolution, type RefreshBody, type RegisterBody, type RelatedSearch, type RemoteOption, type RemotePermit, type RemoteTimezone, type ResetPasswordBody, SDK_VERSION, type SaveJobBody, type SavedJob, type SavedJobsListQuery, type SearchEnvelope, type Seniority, type StorageMode, type StorefrontPagination, type TaxonomyGeo, type TaxonomyResolution, type VerifyEmailBody, createBoardClient, isBoardApiError, isBoardPasswordRequired, isConflict, isForbidden, isNotFound, isRateLimited, isUnauthorized, isValidationError };