{ "openapi": "3.0.3", "info": { "title": "Cavuno v1 REST API", "version": "1.0.0", "description": "The Cavuno API is organized around REST. Our API has predictable resource-oriented URLs, accepts JSON-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs.\n\n## Base URL\n\nProduction: `https://api.cavuno.com/v1`\n\nAll API requests must be made over HTTPS. Calls made over plain HTTP will fail.\n\n## Authentication\n\nThe Cavuno API uses API keys to authenticate requests. You can view and manage your API keys in the Cavuno dashboard, under Settings → Developer → API keys.\n\nCavuno API keys have the prefix `cavuno_live_`. Your API keys carry many privileges, so be sure to keep them secure. Do not share your secret API keys in publicly accessible areas such as GitHub, client-side code, and so forth.\n\nAuthentication to the API is performed via Bearer auth. Provide your API key as the bearer token in the `Authorization` header:\n\n```bash\ncurl https://api.cavuno.com/v1/jobs \\\n -H \"Authorization: Bearer YOUR_SECRET_API_KEY\"\n```\n\nAPI requests without authentication will fail.\n\n## Rate limits\n\nThe Cavuno API has rate limits in place to ensure stability and reliability. By default, API keys are limited to 100 requests per minute. If you exceed your limit, requests return an HTTP 429 response with a `Retry-After` header indicating when you can try again.\n\nIf you have a use case that needs a higher limit, contact support.\n\n## Idempotency\n\nThe API supports idempotency for safely retrying requests without accidentally performing the same operation twice. For example, if a request to create a job fails due to a network connection error, you can safely retry the request with the same idempotency key, and we'll guarantee that only one job is created.\n\nTo perform an idempotent request, provide an additional `Idempotency-Key` header on any `POST`, `PATCH`, or `DELETE` request:\n\n```bash\ncurl https://api.cavuno.com/v1/jobs \\\n -X POST \\\n -H \"Authorization: Bearer cavuno_live_...\" \\\n -H \"Idempotency-Key: $(uuidgen)\" \\\n -H \"Content-Type: application/json\" \\\n -d '{ \"title\": \"Senior Engineer\" }'\n```\n\n## Errors\n\nCavuno uses conventional HTTP response codes to indicate the success or failure of an API request. In general: codes in the `2xx` range indicate success, codes in the `4xx` range indicate an error that failed given the information provided (e.g., a required parameter was omitted), and codes in the `5xx` range indicate an error with Cavuno's servers (these are rare).\n\nError responses include a JSON body with details:\n\n```json\n{\n \"error\": {\n \"code\": \"validation_bad_request\",\n \"message\": \"Field 'title' is required.\",\n \"requestId\": \"req_...\"\n }\n}\n```\n\nSome errors carry an additional `details` field with structured context, such as per-field validation issues.\n\nWhen contacting support about a failed request, include the `requestId` value. It is the fastest way for us to find your request in our logs.\n", "contact": { "name": "Cavuno", "url": "https://cavuno.com" } }, "servers": [ { "url": "https://api.cavuno.com/v1", "description": "Production" } ], "security": [ { "bearerAuth": [] } ], "externalDocs": { "description": "Cavuno API reference", "url": "https://cavuno.com/docs/api" }, "paths": { "/analytics/overview": { "get": { "summary": "Get analytics overview", "description": "Typed Board homepage analytics overview for the authenticated Board: sessions, page views, average session duration, apply clicks, and conditional impressions/revenue metrics. Omits unavailable conditional metrics rather than returning provider connection state. Inclusive UTC date-only range; defaults to the last 30 completed UTC days ending yesterday. Max range 366 days.", "parameters": [ { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "description": "Inclusive range start (UTC date-only YYYY-MM-DD)." }, "required": false, "description": "Inclusive range start (UTC date-only YYYY-MM-DD).", "name": "start", "in": "query" }, { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "description": "Inclusive range end (UTC date-only YYYY-MM-DD)." }, "required": false, "description": "Inclusive range end (UTC date-only YYYY-MM-DD).", "name": "end", "in": "query" } ], "responses": { "200": { "description": "Analytics overview for the requested range.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AnalyticsOverview" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Analytics" ], "operationId": "getAnalyticsOverview" } }, "/analytics/traffic": { "get": { "summary": "Get analytics traffic tables", "description": "Typed Board homepage traffic breakdowns: top pages, sources, locations, and devices with apply-click attribution. Sources are normalized referrers (never full URLs). Inclusive UTC date-only range; defaults to the last 30 completed UTC days ending yesterday. Max range 366 days. `limit` caps each table (1–10, default 10).", "parameters": [ { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "description": "Inclusive range start (UTC date-only YYYY-MM-DD)." }, "required": false, "description": "Inclusive range start (UTC date-only YYYY-MM-DD).", "name": "start", "in": "query" }, { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "description": "Inclusive range end (UTC date-only YYYY-MM-DD)." }, "required": false, "description": "Inclusive range end (UTC date-only YYYY-MM-DD).", "name": "end", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 10, "description": "Max rows per traffic table (1–10). Defaults to 10." }, "required": false, "description": "Max rows per traffic table (1–10). Defaults to 10.", "name": "limit", "in": "query" } ], "responses": { "200": { "description": "Analytics traffic tables for the requested range.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AnalyticsTraffic" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Analytics" ], "operationId": "getAnalyticsTraffic" } }, "/backfill/companies": { "get": { "summary": "List Backfill companies", "description": "List Cavuno companies for one Backfill dashboard tab state. Internal candidate IDs and scores are never returned. Candidates (index/name/website only) appear solely for `needs_match`.", "parameters": [ { "schema": { "type": "string", "enum": [ "backfilling", "available", "needs_match", "not_backfilling" ], "description": "Dashboard tab state: backfilling | available | needs_match | not_backfilling." }, "required": true, "description": "Dashboard tab state: backfilling | available | needs_match | not_backfilling.", "name": "state", "in": "query" }, { "schema": { "type": "string", "maxLength": 200, "description": "Case-insensitive name substring filter." }, "required": false, "description": "Case-insensitive name substring filter.", "name": "search", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 100 }, "required": false, "name": "limit", "in": "query" }, { "schema": { "type": "string", "minLength": 1 }, "required": false, "name": "cursor", "in": "query" } ], "responses": { "200": { "description": "A page of Backfill companies.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/BackfillCompany" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Backfill" ], "operationId": "listBackfillCompanies" } }, "/backfill/companies/bulk-start": { "post": { "summary": "Bulk-start Backfill for companies", "description": "Start backfill for up to 100 Cavuno company IDs. Preserves order and returns per-item success or product error without provider detail (a not-Backfillable company reports `company_not_backfillable`). Requires an `Idempotency-Key` header.", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulkBackfillCompaniesBody" } } } }, "responses": { "200": { "description": "Ordered per-item results.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BackfillBulkResult" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Backfill" ], "operationId": "createBackfillCompaniesBulkStart" } }, "/backfill/companies/bulk-stop": { "post": { "summary": "Bulk-stop Backfill for companies", "description": "Stop backfill for up to 100 Cavuno company IDs. Ordered partial-success semantics. Requires an `Idempotency-Key` header.", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulkBackfillCompaniesBody" } } } }, "responses": { "200": { "description": "Ordered per-item results.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BackfillBulkResult" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Backfill" ], "operationId": "createBackfillCompaniesBulkStop" } }, "/backfill/companies/{companyId}/mark-no-match": { "post": { "summary": "Mark a Backfill company as no match", "description": "Record that none of the candidates match (same as the dashboard \"None of these\" action). Requires an `Idempotency-Key` header.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "Cavuno company ID from the companies or Backfill list." }, "required": true, "description": "Cavuno company ID from the companies or Backfill list.", "name": "companyId", "in": "path" } ], "responses": { "200": { "description": "The company after mark-no-match.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BackfillCompany" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Backfill" ], "operationId": "createBackfillCompanyMarkNoMatch" } }, "/backfill/companies/{companyId}/match": { "post": { "summary": "Confirm a Backfill company match", "description": "Link a needs_match company to a candidate by short-lived list index. The live candidate list is re-read and re-sorted server-side; a stale index returns `backfill_candidate_conflict`. Requires an `Idempotency-Key` header.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "Cavuno company ID from the companies or Backfill list." }, "required": true, "description": "Cavuno company ID from the companies or Backfill list.", "name": "companyId", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MatchBackfillCompanyBody" } } } }, "responses": { "200": { "description": "The company after match.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BackfillCompany" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Backfill" ], "operationId": "createBackfillCompanyMatch" } }, "/backfill/companies/{companyId}/start": { "post": { "summary": "Start Backfill for a company", "description": "Start collecting jobs for a Cavuno company. Registration uses an existing provider match or the company website, resolved server-side. A company with no supported ATS detected on its website and no confirmed match is rejected with `company_not_backfillable` (422). Requires an `Idempotency-Key` header.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "Cavuno company ID from the companies or Backfill list." }, "required": true, "description": "Cavuno company ID from the companies or Backfill list.", "name": "companyId", "in": "path" } ], "responses": { "200": { "description": "The company after start.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BackfillCompany" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Backfill" ], "operationId": "createBackfillCompanyStart" } }, "/backfill/companies/{companyId}/stop": { "post": { "summary": "Stop Backfill for a company", "description": "Stop collecting jobs for a Cavuno company. Requires a website on file (same as the dashboard). Requires an `Idempotency-Key` header.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "Cavuno company ID from the companies or Backfill list." }, "required": true, "description": "Cavuno company ID from the companies or Backfill list.", "name": "companyId", "in": "path" } ], "responses": { "200": { "description": "The company after stop.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BackfillCompany" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Backfill" ], "operationId": "createBackfillCompanyStop" } }, "/backfill/progress": { "get": { "summary": "Get Backfill progress", "description": "Return the aggregate Backfill progress for the Board — the same status and job counts ordinary users see during onboarding. Returns JSON `null` when no progress exists. Does not expose sync-run history, provider run IDs, or per-run error detail.", "responses": { "200": { "description": "Aggregate Backfill progress, or `null` when the Board has none.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BackfillProgress" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Backfill" ], "operationId": "getBackfillProgress" } }, "/backfill/rules": { "get": { "summary": "List Backfill rules", "description": "List named Backfill rules for the Board. Excludes the provider company subscription. Provider vertical keys and rule DSL are never returned.", "responses": { "200": { "description": "A list of Backfill rules.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/BackfillRule" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Backfill" ], "operationId": "listBackfillRules" }, "post": { "summary": "Create a Backfill rule", "description": "Create a named Backfill rule using the same typed rule-card conditions and filters as the dashboard form. Requires an `Idempotency-Key` header.", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateBackfillRuleBody" } } } }, "responses": { "201": { "description": "The created Backfill rule.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BackfillRule" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Backfill" ], "operationId": "createBackfillRule" } }, "/backfill/rules/{id}": { "get": { "summary": "Retrieve a Backfill rule", "description": "Retrieve a single Backfill rule by its Cavuno-owned ID.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The Backfill rule ID returned by create or list endpoints." }, "required": true, "description": "The Backfill rule ID returned by create or list endpoints.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "The Backfill rule.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BackfillRule" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Backfill" ], "operationId": "getBackfillRule" }, "patch": { "summary": "Update a Backfill rule", "description": "Partially update a Backfill rule. Omitted fields keep their current values, matching the dashboard edit form. Requires an `Idempotency-Key` header.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The Backfill rule ID returned by create or list endpoints." }, "required": true, "description": "The Backfill rule ID returned by create or list endpoints.", "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateBackfillRuleBody" } } } }, "responses": { "200": { "description": "The updated Backfill rule.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BackfillRule" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Backfill" ], "operationId": "updateBackfillRule" }, "delete": { "summary": "Delete a Backfill rule", "description": "Delete a named Backfill rule. Requires an `Idempotency-Key` header.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The Backfill rule ID returned by create or list endpoints." }, "required": true, "description": "The Backfill rule ID returned by create or list endpoints.", "name": "id", "in": "path" } ], "responses": { "204": { "description": "The rule was deleted." }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Backfill" ], "operationId": "deleteBackfillRule" } }, "/billing/checkout": { "post": { "summary": "Create hosted checkout for a plan", "description": "Returns a hosted human-consent URL for the target plan. Requires `billing.manage`.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BillingCheckoutBody" } } } }, "responses": { "200": { "description": "Hosted checkout session created.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BillingCheckout" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Billing" ], "operationId": "createCheckoutSession" } }, "/billing/connect": { "get": { "summary": "Get payment connection status", "description": "Returns the Board's normalized payment connection readiness without provider identifiers or raw provider requirements.", "responses": { "200": { "description": "The Board payment connection status.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BillingConnect" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Billing" ], "operationId": "getBillingConnect" } }, "/billing/subscription": { "get": { "summary": "Get the account platform subscription", "description": "Returns the Board's Cavuno plan, status, renewal state, and included product capabilities. Provider identifiers are never returned.", "responses": { "200": { "description": "The account billing subscription.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BillingSubscription" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Billing" ], "operationId": "getBillingSubscription" } }, "/billing/upgrade": { "post": { "summary": "Upgrade the account plan", "description": "Creates a hosted human-consent handoff for an upgrade. It never charges a saved payment method directly. Requires `billing.manage` and an `Idempotency-Key` header.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BillingUpgradeBody" } } } }, "responses": { "200": { "description": "Upgrade completed or checkout required.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BillingUpgrade" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Billing" ], "operationId": "upgradeSubscription" } }, "/blog/authors": { "get": { "summary": "List blog authors", "description": "Returns a list of your blog authors. The authors are returned sorted by update date, with the most recently updated authors appearing first.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results." }, "required": false, "description": "An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results.", "name": "cursor", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "description": "A limit on the number of objects to be returned. Limit can range between 1 and 100." }, "required": false, "description": "A limit on the number of objects to be returned. Limit can range between 1 and 100.", "example": 20, "name": "limit", "in": "query" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/blog/authors" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/BlogAuthor" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "400": { "description": "The request was malformed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog authors" ], "operationId": "listBlogAuthors" }, "post": { "summary": "Create a blog author", "description": "Creates a new blog author. The request is idempotent when an `Idempotency-Key` header is supplied.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateAuthorBody" } } } }, "responses": { "201": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlogAuthor" } } } }, "400": { "description": "The request was malformed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Another author already uses the same slug.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog authors" ], "operationId": "createBlogAuthor" } }, "/blog/authors/export": { "get": { "summary": "Export blog authors", "description": "Exports the account’s blog authors. `format=json` returns an inline list of export rows (max 10,000; fields mirror the CSV columns, camelCase). `format=csv` (default) returns `202` with an `exports.generate` operation — poll it, then download the CSV from `GET /v1/operations/{id}/download` once it succeeds. Requires `blog.read`.", "parameters": [ { "schema": { "type": "string", "enum": [ "csv", "json" ], "default": "csv", "description": "Export format. `json` streams an inline list of blog author export rows (capped at 10,000 rows); `csv` (default) starts an async `exports.generate` operation." }, "required": false, "description": "Export format. `json` streams an inline list of blog author export rows (capped at 10,000 rows); `csv` (default) starts an async `exports.generate` operation.", "name": "format", "in": "query" } ], "responses": { "200": { "description": "Inline JSON export (`format=json`).", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/blog/authors/export" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/ExportRow" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "202": { "description": "An `exports.generate` operation was started (`format=csv`). Poll the operation; once it succeeds, download the CSV from `GET /v1/operations/{id}/download`.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OperationResource" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog authors" ], "operationId": "exportBlogAuthors" } }, "/blog/authors/{id}": { "get": { "summary": "Retrieve a blog author", "description": "Retrieves the details of an existing blog author. You only need to supply the unique author ID that was returned upon author creation.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The author's opaque object `id`: the `id` field returned by the author endpoints (e.g. `a4u7t9k2d6q0r3s8v1w5x9y2z6b0c4m7`). This is NOT the `slug` or name; passing a slug like `jane-doe` returns 404. To look up an author by name or slug, use `GET /v1/blog/authors` and read the returned `id`." }, "required": true, "description": "The author's opaque object `id`: the `id` field returned by the author endpoints (e.g. `a4u7t9k2d6q0r3s8v1w5x9y2z6b0c4m7`). This is NOT the `slug` or name; passing a slug like `jane-doe` returns 404. To look up an author by name or slug, use `GET /v1/blog/authors` and read the returned `id`.", "example": "a4u7t9k2d6q0r3s8v1w5x9y2z6b0c4m7", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlogAuthor" } } } }, "404": { "description": "Author not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog authors" ], "operationId": "getBlogAuthor" }, "patch": { "summary": "Update a blog author", "description": "Updates the specified blog author by setting the values of the parameters passed. Any parameters not provided will be left unchanged. The request is idempotent when an `Idempotency-Key` header is supplied.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The author's opaque object `id`: the `id` field returned by the author endpoints (e.g. `a4u7t9k2d6q0r3s8v1w5x9y2z6b0c4m7`). This is NOT the `slug` or name; passing a slug like `jane-doe` returns 404. To look up an author by name or slug, use `GET /v1/blog/authors` and read the returned `id`." }, "required": true, "description": "The author's opaque object `id`: the `id` field returned by the author endpoints (e.g. `a4u7t9k2d6q0r3s8v1w5x9y2z6b0c4m7`). This is NOT the `slug` or name; passing a slug like `jane-doe` returns 404. To look up an author by name or slug, use `GET /v1/blog/authors` and read the returned `id`.", "example": "a4u7t9k2d6q0r3s8v1w5x9y2z6b0c4m7", "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateAuthorBody" } } } }, "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlogAuthor" } } } }, "400": { "description": "The request was malformed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Author not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Another author already uses the same slug.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog authors" ], "operationId": "updateBlogAuthor" }, "delete": { "summary": "Delete a blog author", "description": "Permanently deletes a blog author. Posts referencing this author keep the stale ID in their `authorIds` array (no cascade). It cannot be undone.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The author's opaque object `id`: the `id` field returned by the author endpoints (e.g. `a4u7t9k2d6q0r3s8v1w5x9y2z6b0c4m7`). This is NOT the `slug` or name; passing a slug like `jane-doe` returns 404. To look up an author by name or slug, use `GET /v1/blog/authors` and read the returned `id`." }, "required": true, "description": "The author's opaque object `id`: the `id` field returned by the author endpoints (e.g. `a4u7t9k2d6q0r3s8v1w5x9y2z6b0c4m7`). This is NOT the `slug` or name; passing a slug like `jane-doe` returns 404. To look up an author by name or slug, use `GET /v1/blog/authors` and read the returned `id`.", "example": "a4u7t9k2d6q0r3s8v1w5x9y2z6b0c4m7", "name": "id", "in": "path" } ], "responses": { "204": { "description": "Successful response." }, "404": { "description": "Author not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog authors" ], "operationId": "deleteBlogAuthor" } }, "/blog/posts": { "get": { "summary": "List blog posts", "description": "Returns a list of blog posts for the account, most recently updated first. Filter by a single `status`.", "parameters": [ { "schema": { "type": "string", "minLength": 1 }, "required": false, "name": "cursor", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 100 }, "required": false, "name": "limit", "in": "query" }, { "schema": { "type": "string", "enum": [ "draft", "scheduled", "published" ] }, "required": false, "name": "status", "in": "query" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/blog/posts" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/BlogPostSummary" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "400": { "description": "The request was malformed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog posts" ], "operationId": "listBlogPosts" }, "post": { "summary": "Create a blog post", "description": "Creates a blog post. New posts default to `status: \"draft\"`; publish explicitly via `POST /v1/blog/posts/{id}/publish`. The `html` body is sanitized server-side.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateBlogPostBody" } } } }, "responses": { "201": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlogPost" } } } }, "400": { "description": "The request was malformed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog posts" ], "operationId": "createBlogPost" } }, "/blog/posts/batch": { "post": { "summary": "Run a batch of blog post operations", "description": "Runs up to 50 blog post operations in a single request (5 MB body limit). Each sub-operation runs independently. A `publish`/`unpublish` sub-op uses `{ method: \"POST\", action: \"publish\", resourceId }` and requires `blog.publish`. Idempotency keys are honored on the batch itself, not on individual sub-operations.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlogPostsBatchRequest" } } } }, "responses": { "200": { "description": "Successful response. Inspect each entry of the `data` array for the per-sub-operation status.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "batch_result" ] }, "data": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "status": { "type": "number" }, "data": { "nullable": true }, "error": { "type": "object", "properties": { "code": { "type": "string" }, "message": { "type": "string" }, "details": { "nullable": true } }, "required": [ "code", "message" ] } }, "required": [ "id", "status" ] } } }, "required": [ "object", "data" ] } } } }, "413": { "description": "The request body exceeded 5 MB.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog posts" ], "operationId": "batchBlogPosts" } }, "/blog/posts/export": { "get": { "summary": "Export blog posts", "description": "Exports the account’s blog posts. `format=json` returns an inline list of export rows (max 10,000; fields mirror the CSV columns, camelCase). `format=csv` (default) returns `202` with an `exports.generate` operation — poll it, then download the CSV from `GET /v1/operations/{id}/download` once it succeeds. Requires `blog.read`.", "parameters": [ { "schema": { "type": "string", "enum": [ "csv", "json" ], "default": "csv", "description": "Export format. `json` streams an inline list of blog post export rows (capped at 10,000 rows); `csv` (default) starts an async `exports.generate` operation." }, "required": false, "description": "Export format. `json` streams an inline list of blog post export rows (capped at 10,000 rows); `csv` (default) starts an async `exports.generate` operation.", "name": "format", "in": "query" } ], "responses": { "200": { "description": "Inline JSON export (`format=json`).", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/blog/posts/export" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/ExportRow" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "202": { "description": "An `exports.generate` operation was started (`format=csv`). Poll the operation; once it succeeds, download the CSV from `GET /v1/operations/{id}/download`.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OperationResource" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog posts" ], "operationId": "exportBlogPosts" } }, "/blog/posts/search": { "post": { "summary": "Search blog posts", "description": "Lexical title search across all statuses (includes drafts). Optionally narrow to a single `status`.", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SearchBlogPostsBody" } } } }, "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "search_result" ] }, "url": { "type": "string", "example": "/v1/blog/posts/search" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/BlogPostSummary" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog posts" ], "operationId": "searchBlogPosts" } }, "/blog/posts/{id}": { "get": { "summary": "Retrieve a blog post", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The post's opaque object `id`: the `id` field returned by the blog-post endpoints (e.g. `b3p8m2k7d9q4x0r5t1v6w8y2z7a4c0n3`). This is NOT the `slug` or title; passing a slug like `my-first-post` returns 404. To look up a post by title or slug, use `GET /v1/blog/posts` or `POST /v1/blog/posts/search` and read the returned `id`." }, "required": true, "description": "The post's opaque object `id`: the `id` field returned by the blog-post endpoints (e.g. `b3p8m2k7d9q4x0r5t1v6w8y2z7a4c0n3`). This is NOT the `slug` or title; passing a slug like `my-first-post` returns 404. To look up a post by title or slug, use `GET /v1/blog/posts` or `POST /v1/blog/posts/search` and read the returned `id`.", "example": "b3p8m2k7d9q4x0r5t1v6w8y2z7a4c0n3", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlogPost" } } } }, "404": { "description": "Blog post not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog posts" ], "operationId": "getBlogPost" }, "patch": { "summary": "Update a blog post", "description": "Updates a blog post. A `status` value is rejected with `blog_invalid_transition` unless it is the scheduling carve-out (`status: \"scheduled\"` with a future `publishedAt`); use the publish/unpublish endpoints for other lifecycle changes.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The post's opaque object `id`: the `id` field returned by the blog-post endpoints (e.g. `b3p8m2k7d9q4x0r5t1v6w8y2z7a4c0n3`). This is NOT the `slug` or title; passing a slug like `my-first-post` returns 404. To look up a post by title or slug, use `GET /v1/blog/posts` or `POST /v1/blog/posts/search` and read the returned `id`." }, "required": true, "description": "The post's opaque object `id`: the `id` field returned by the blog-post endpoints (e.g. `b3p8m2k7d9q4x0r5t1v6w8y2z7a4c0n3`). This is NOT the `slug` or title; passing a slug like `my-first-post` returns 404. To look up a post by title or slug, use `GET /v1/blog/posts` or `POST /v1/blog/posts/search` and read the returned `id`.", "example": "b3p8m2k7d9q4x0r5t1v6w8y2z7a4c0n3", "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateBlogPostBody" } } } }, "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlogPost" } } } }, "400": { "description": "Malformed request or an invalid status transition.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Blog post not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The slug change collides with an existing post.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog posts" ], "operationId": "updateBlogPost" }, "delete": { "summary": "Delete a blog post", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The post's opaque object `id`: the `id` field returned by the blog-post endpoints (e.g. `b3p8m2k7d9q4x0r5t1v6w8y2z7a4c0n3`). This is NOT the `slug` or title; passing a slug like `my-first-post` returns 404. To look up a post by title or slug, use `GET /v1/blog/posts` or `POST /v1/blog/posts/search` and read the returned `id`." }, "required": true, "description": "The post's opaque object `id`: the `id` field returned by the blog-post endpoints (e.g. `b3p8m2k7d9q4x0r5t1v6w8y2z7a4c0n3`). This is NOT the `slug` or title; passing a slug like `my-first-post` returns 404. To look up a post by title or slug, use `GET /v1/blog/posts` or `POST /v1/blog/posts/search` and read the returned `id`.", "example": "b3p8m2k7d9q4x0r5t1v6w8y2z7a4c0n3", "name": "id", "in": "path" } ], "responses": { "204": { "description": "Successful response." }, "404": { "description": "Blog post not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog posts" ], "operationId": "deleteBlogPost" } }, "/blog/posts/{id}/publish": { "post": { "summary": "Publish a blog post", "description": "Publishes a draft or scheduled post, making it visible on the public board. Takes no request body. `publishedAt` is stamped on the first publish and preserved on a later republish.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The post's opaque object `id`: the `id` field returned by the blog-post endpoints (e.g. `b3p8m2k7d9q4x0r5t1v6w8y2z7a4c0n3`). This is NOT the `slug` or title; passing a slug like `my-first-post` returns 404. To look up a post by title or slug, use `GET /v1/blog/posts` or `POST /v1/blog/posts/search` and read the returned `id`." }, "required": true, "description": "The post's opaque object `id`: the `id` field returned by the blog-post endpoints (e.g. `b3p8m2k7d9q4x0r5t1v6w8y2z7a4c0n3`). This is NOT the `slug` or title; passing a slug like `my-first-post` returns 404. To look up a post by title or slug, use `GET /v1/blog/posts` or `POST /v1/blog/posts/search` and read the returned `id`.", "example": "b3p8m2k7d9q4x0r5t1v6w8y2z7a4c0n3", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlogPost" } } } }, "404": { "description": "Blog post not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The post is already published.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog posts" ], "operationId": "publishBlogPost" } }, "/blog/posts/{id}/toggle-featured": { "post": { "summary": "Toggle a blog post's featured flag", "description": "Flips the post's `featured` flag and returns the updated post. Takes no request body.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The post's opaque object `id`: the `id` field returned by the blog-post endpoints (e.g. `b3p8m2k7d9q4x0r5t1v6w8y2z7a4c0n3`). This is NOT the `slug` or title; passing a slug like `my-first-post` returns 404. To look up a post by title or slug, use `GET /v1/blog/posts` or `POST /v1/blog/posts/search` and read the returned `id`." }, "required": true, "description": "The post's opaque object `id`: the `id` field returned by the blog-post endpoints (e.g. `b3p8m2k7d9q4x0r5t1v6w8y2z7a4c0n3`). This is NOT the `slug` or title; passing a slug like `my-first-post` returns 404. To look up a post by title or slug, use `GET /v1/blog/posts` or `POST /v1/blog/posts/search` and read the returned `id`.", "example": "b3p8m2k7d9q4x0r5t1v6w8y2z7a4c0n3", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlogPost" } } } }, "404": { "description": "Blog post not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog posts" ], "operationId": "toggleFeaturedBlogPost" } }, "/blog/posts/{id}/unpublish": { "post": { "summary": "Unpublish a blog post", "description": "Reverts a published post to a draft, removing it from the public board. Takes no request body. The stored `publishedAt` is preserved so a later republish keeps the original publish date.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The post's opaque object `id`: the `id` field returned by the blog-post endpoints (e.g. `b3p8m2k7d9q4x0r5t1v6w8y2z7a4c0n3`). This is NOT the `slug` or title; passing a slug like `my-first-post` returns 404. To look up a post by title or slug, use `GET /v1/blog/posts` or `POST /v1/blog/posts/search` and read the returned `id`." }, "required": true, "description": "The post's opaque object `id`: the `id` field returned by the blog-post endpoints (e.g. `b3p8m2k7d9q4x0r5t1v6w8y2z7a4c0n3`). This is NOT the `slug` or title; passing a slug like `my-first-post` returns 404. To look up a post by title or slug, use `GET /v1/blog/posts` or `POST /v1/blog/posts/search` and read the returned `id`.", "example": "b3p8m2k7d9q4x0r5t1v6w8y2z7a4c0n3", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlogPost" } } } }, "404": { "description": "Blog post not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The post is not currently published.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog posts" ], "operationId": "unpublishBlogPost" } }, "/blog/tags": { "get": { "summary": "List blog tags", "description": "Returns a list of your blog tags. The tags are returned sorted by update date, with the most recently updated tags appearing first.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results." }, "required": false, "description": "An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results.", "name": "cursor", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "description": "A limit on the number of objects to be returned. Limit can range between 1 and 100." }, "required": false, "description": "A limit on the number of objects to be returned. Limit can range between 1 and 100.", "example": 20, "name": "limit", "in": "query" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/blog/tags" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/BlogTag" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "400": { "description": "The request was malformed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog tags" ], "operationId": "listBlogTags" }, "post": { "summary": "Create a blog tag", "description": "Creates a new blog tag. The request is idempotent when an `Idempotency-Key` header is supplied.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateTagBody" } } } }, "responses": { "201": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlogTag" } } } }, "400": { "description": "The request was malformed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Another tag already uses the same slug.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog tags" ], "operationId": "createBlogTag" } }, "/blog/tags/export": { "get": { "summary": "Export blog tags", "description": "Exports the account’s blog tags. `format=json` returns an inline list of export rows (max 10,000; fields mirror the CSV columns, camelCase). `format=csv` (default) returns `202` with an `exports.generate` operation — poll it, then download the CSV from `GET /v1/operations/{id}/download` once it succeeds. Requires `blog.read`.", "parameters": [ { "schema": { "type": "string", "enum": [ "csv", "json" ], "default": "csv", "description": "Export format. `json` streams an inline list of blog tag export rows (capped at 10,000 rows); `csv` (default) starts an async `exports.generate` operation." }, "required": false, "description": "Export format. `json` streams an inline list of blog tag export rows (capped at 10,000 rows); `csv` (default) starts an async `exports.generate` operation.", "name": "format", "in": "query" } ], "responses": { "200": { "description": "Inline JSON export (`format=json`).", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/blog/tags/export" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/ExportRow" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "202": { "description": "An `exports.generate` operation was started (`format=csv`). Poll the operation; once it succeeds, download the CSV from `GET /v1/operations/{id}/download`.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OperationResource" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog tags" ], "operationId": "exportBlogTags" } }, "/blog/tags/{id}": { "get": { "summary": "Retrieve a blog tag", "description": "Retrieves the details of an existing blog tag. You only need to supply the unique tag ID that was returned upon tag creation.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The tag's opaque object `id`: the `id` field returned by the tag endpoints (e.g. `t1g5k9d3q7m0p4r8s2v6w1x5y9z3b7c0`). This is NOT the `slug` or name; passing a slug like `engineering` returns 404. To look up a tag by name or slug, use `GET /v1/blog/tags` and read the returned `id`." }, "required": true, "description": "The tag's opaque object `id`: the `id` field returned by the tag endpoints (e.g. `t1g5k9d3q7m0p4r8s2v6w1x5y9z3b7c0`). This is NOT the `slug` or name; passing a slug like `engineering` returns 404. To look up a tag by name or slug, use `GET /v1/blog/tags` and read the returned `id`.", "example": "t1g5k9d3q7m0p4r8s2v6w1x5y9z3b7c0", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlogTag" } } } }, "404": { "description": "Tag not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog tags" ], "operationId": "getBlogTag" }, "patch": { "summary": "Update a blog tag", "description": "Updates the specified blog tag by setting the values of the parameters passed. Any parameters not provided will be left unchanged. The request is idempotent when an `Idempotency-Key` header is supplied.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The tag's opaque object `id`: the `id` field returned by the tag endpoints (e.g. `t1g5k9d3q7m0p4r8s2v6w1x5y9z3b7c0`). This is NOT the `slug` or name; passing a slug like `engineering` returns 404. To look up a tag by name or slug, use `GET /v1/blog/tags` and read the returned `id`." }, "required": true, "description": "The tag's opaque object `id`: the `id` field returned by the tag endpoints (e.g. `t1g5k9d3q7m0p4r8s2v6w1x5y9z3b7c0`). This is NOT the `slug` or name; passing a slug like `engineering` returns 404. To look up a tag by name or slug, use `GET /v1/blog/tags` and read the returned `id`.", "example": "t1g5k9d3q7m0p4r8s2v6w1x5y9z3b7c0", "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateTagBody" } } } }, "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlogTag" } } } }, "400": { "description": "The request was malformed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Tag not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Another tag already uses the same slug.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog tags" ], "operationId": "updateBlogTag" }, "delete": { "summary": "Delete a blog tag", "description": "Permanently deletes a blog tag. Posts referencing this tag keep the stale ID in their `tagIds` array (no cascade). It cannot be undone.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The tag's opaque object `id`: the `id` field returned by the tag endpoints (e.g. `t1g5k9d3q7m0p4r8s2v6w1x5y9z3b7c0`). This is NOT the `slug` or name; passing a slug like `engineering` returns 404. To look up a tag by name or slug, use `GET /v1/blog/tags` and read the returned `id`." }, "required": true, "description": "The tag's opaque object `id`: the `id` field returned by the tag endpoints (e.g. `t1g5k9d3q7m0p4r8s2v6w1x5y9z3b7c0`). This is NOT the `slug` or name; passing a slug like `engineering` returns 404. To look up a tag by name or slug, use `GET /v1/blog/tags` and read the returned `id`.", "example": "t1g5k9d3q7m0p4r8s2v6w1x5y9z3b7c0", "name": "id", "in": "path" } ], "responses": { "204": { "description": "Successful response." }, "404": { "description": "Tag not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Blog tags" ], "operationId": "deleteBlogTag" } }, "/candidates": { "get": { "summary": "List candidates", "description": "Returns the candidates (board users with role `candidate`) of the authenticated account. Per-candidate saved-job and alert counts are not inlined here. Fetch them via `GET /v1/candidates/{id}`. Requires `candidates.read`.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "Pagination cursor." }, "required": false, "description": "Pagination cursor.", "name": "cursor", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Page size (1–100, default 50)." }, "required": false, "description": "Page size (1–100, default 50).", "name": "limit", "in": "query" }, { "schema": { "type": "string", "minLength": 1, "description": "Case-insensitive substring match on the candidate email or display name." }, "required": false, "description": "Case-insensitive substring match on the candidate email or display name.", "name": "search", "in": "query" }, { "schema": { "type": "string", "minLength": 1, "description": "Exact public-profile handle lookup." }, "required": false, "description": "Exact public-profile handle lookup.", "name": "handle", "in": "query" }, { "schema": { "type": "string", "enum": [ "true", "false" ], "description": "Filter by whether the candidate has uploaded a resume." }, "required": false, "description": "Filter by whether the candidate has uploaded a resume.", "name": "hasResume", "in": "query" }, { "schema": { "type": "string", "format": "date-time", "description": "ISO-8601 lower bound (inclusive) on registration date." }, "required": false, "description": "ISO-8601 lower bound (inclusive) on registration date.", "name": "createdFrom", "in": "query" }, { "schema": { "type": "string", "format": "date-time", "description": "ISO-8601 upper bound (inclusive) on registration date." }, "required": false, "description": "ISO-8601 upper bound (inclusive) on registration date.", "name": "createdTo", "in": "query" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/candidates" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Candidate" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Candidates" ], "operationId": "listCandidates" } }, "/candidates/export": { "get": { "summary": "Export candidates", "description": "Exports the account’s candidates. `format=json` returns an inline list of export rows (max 10,000; fields mirror the CSV columns, camelCase). Resume blobs are never inlined — a candidate with a resume carries a `resumeUrl` pointing at the authenticated `GET /v1/candidates/{id}/resume` stream. `format=csv` (default) returns `202` with an `exports.generate` operation — poll it, then download the CSV from `GET /v1/operations/{id}/download` once it succeeds. Requires `candidates.read`.", "parameters": [ { "schema": { "type": "string", "enum": [ "csv", "json" ], "default": "csv", "description": "Export format. `json` streams an inline list of candidate export rows (capped at 10,000 rows); `csv` (default) starts an async `exports.generate` operation." }, "required": false, "description": "Export format. `json` streams an inline list of candidate export rows (capped at 10,000 rows); `csv` (default) starts an async `exports.generate` operation.", "name": "format", "in": "query" } ], "responses": { "200": { "description": "Inline JSON export (`format=json`).", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/candidates/export" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/ExportRow" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "202": { "description": "An `exports.generate` operation was started (`format=csv`). Poll the operation; once it succeeds, download the CSV from `GET /v1/operations/{id}/download`.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OperationResource" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Candidates" ], "operationId": "exportCandidates" } }, "/candidates/{id}": { "get": { "summary": "Get a candidate", "description": "Returns a single candidate with profile detail, saved-job / alert counts, and a nullable protected resume download path. Requires `candidates.read`.", "parameters": [ { "schema": { "type": "string", "description": "The candidate id." }, "required": true, "description": "The candidate id.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CandidateDetail" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Candidates" ], "operationId": "getCandidate" }, "delete": { "summary": "Delete a candidate", "description": "Permanently erases a candidate and all associated data (GDPR cascade). Always asynchronous: returns `202` with a `candidates.remove` operation to poll. Requires `candidates.manage`.", "parameters": [ { "schema": { "type": "string", "description": "The candidate id." }, "required": true, "description": "The candidate id.", "name": "id", "in": "path" } ], "responses": { "202": { "description": "Deletion operation accepted.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OperationResource" } } } }, "404": { "description": "Candidate not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Candidates" ], "operationId": "deleteCandidate" } }, "/candidates/{id}/resume": { "get": { "summary": "Download a candidate resume", "description": "Streams the candidate resume through the authenticated Cavuno API. Storage-provider URLs and credentials are never returned. Requires `candidates.read`.", "parameters": [ { "schema": { "type": "string", "description": "The candidate id." }, "required": true, "description": "The candidate id.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "The resume file.", "content": { "application/octet-stream": { "schema": { "type": "string", "format": "binary" } } } }, "404": { "description": "Candidate or resume not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Candidates" ], "operationId": "listCandidateResume" } }, "/companies": { "get": { "summary": "List companies", "description": "Returns a list of your companies. The companies are returned sorted by creation date, with the most recently created companies appearing first.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results." }, "required": false, "description": "An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results.", "name": "cursor", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "description": "A limit on the number of objects to be returned. Limit can range between 1 and 100." }, "required": false, "description": "A limit on the number of objects to be returned. Limit can range between 1 and 100.", "example": 20, "name": "limit", "in": "query" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/companies" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/CompanySummary" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "400": { "description": "The request was malformed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Companies" ], "operationId": "listCompanies" }, "post": { "summary": "Create a company", "description": "Creates a new company. A logo is auto-fetched from `website` when available. The request is idempotent when an `Idempotency-Key` header is supplied.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateCompanyBody" } } } }, "responses": { "201": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Company" } } } }, "400": { "description": "The request was malformed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Another company already uses the same website domain or name.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Companies" ], "operationId": "createCompany" } }, "/companies/batch": { "post": { "summary": "Run a batch of company operations", "description": "Runs up to 100 company operations in a single request, with a 5 MB request body limit. Each sub-operation runs independently. Idempotency keys are honored on the batch itself, not on individual sub-operations.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CompaniesBatchRequest" } } } }, "responses": { "200": { "description": "Successful response. Inspect each entry of the `data` array for the per-sub-operation status.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "batch_result" ] }, "data": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "status": { "type": "number" }, "data": { "nullable": true }, "error": { "type": "object", "properties": { "code": { "type": "string" }, "message": { "type": "string" }, "details": { "nullable": true } }, "required": [ "code", "message" ] } }, "required": [ "id", "status" ] } } }, "required": [ "object", "data" ] } } } }, "413": { "description": "The request body exceeded 5 MB.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Companies" ], "operationId": "batchCompanies" } }, "/companies/export": { "get": { "summary": "Export companies", "description": "Exports the account’s companies. `format=json` returns an inline list of export rows (max 10,000; fields mirror the CSV columns, camelCase). `format=csv` (default) returns `202` with an `exports.generate` operation — poll it, then download the CSV from `GET /v1/operations/{id}/download` once it succeeds. Requires `companies.read`.", "parameters": [ { "schema": { "type": "string", "enum": [ "csv", "json" ], "default": "csv", "description": "Export format. `json` streams an inline list of company export rows (capped at 10,000 rows); `csv` (default) starts an async `exports.generate` operation." }, "required": false, "description": "Export format. `json` streams an inline list of company export rows (capped at 10,000 rows); `csv` (default) starts an async `exports.generate` operation.", "name": "format", "in": "query" } ], "responses": { "200": { "description": "Inline JSON export (`format=json`).", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/companies/export" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/ExportRow" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "202": { "description": "An `exports.generate` operation was started (`format=csv`). Poll the operation; once it succeeds, download the CSV from `GET /v1/operations/{id}/download`.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OperationResource" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Companies" ], "operationId": "exportCompanies" } }, "/companies/find-or-create": { "post": { "summary": "Resolve or create a company", "description": "Resolves an existing company by website domain (and optionally by name), or creates a new one if no match is found. On creation, a logo is auto-fetched from `website` when available. Use `matchByName` to disable name fallback, or `createIfMissing` to disable creation. Useful for workflows that have a name and website but no company ID yet.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FindOrCreateCompanyBody" } } } }, "responses": { "200": { "description": "Successful response. The `matched` field indicates whether the returned company already existed (`true`) or was newly created (`false`).", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/Company" }, { "type": "object", "properties": { "matched": { "type": "boolean" } }, "required": [ "matched" ] } ] } } } }, "404": { "description": "No company matched the supplied `name` or `website`, and `createIfMissing` was set to `false`.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Companies" ], "operationId": "findOrCreateCompany" } }, "/companies/search": { "post": { "summary": "Search companies", "description": "Searches your companies using a free-text query. Results are returned sorted by creation date, with the most recently created companies appearing first.", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SearchCompaniesBody" } } } }, "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "search_result" ] }, "url": { "type": "string", "example": "/v1/companies/search" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Company" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Companies" ], "operationId": "searchCompanies" } }, "/companies/{id}": { "get": { "summary": "Retrieve a company", "description": "Retrieves the details of an existing company. You only need to supply the unique company ID that was returned upon company creation.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The company's opaque object `id`: the `id` field returned by the company endpoints (e.g. `p17xq4c2b9r5gz3e8j0r6t4k7m2n9d5w`). This is NOT the `slug` or display name; passing a slug like `antler` returns 404. To look up a company by name or slug, use `GET /v1/companies`, `POST /v1/companies/search`, or `POST /v1/companies/find-or-create` and read the returned `id`." }, "required": true, "description": "The company's opaque object `id`: the `id` field returned by the company endpoints (e.g. `p17xq4c2b9r5gz3e8j0r6t4k7m2n9d5w`). This is NOT the `slug` or display name; passing a slug like `antler` returns 404. To look up a company by name or slug, use `GET /v1/companies`, `POST /v1/companies/search`, or `POST /v1/companies/find-or-create` and read the returned `id`.", "example": "p17xq4c2b9r5gz3e8j0r6t4k7m2n9d5w", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Company" } } } }, "404": { "description": "Company not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Companies" ], "operationId": "getCompany" }, "patch": { "summary": "Update a company", "description": "Updates the specified company by setting the values of the parameters passed. Any parameters not provided will be left unchanged. The request is idempotent when an `Idempotency-Key` header is supplied.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The company's opaque object `id`: the `id` field returned by the company endpoints (e.g. `p17xq4c2b9r5gz3e8j0r6t4k7m2n9d5w`). This is NOT the `slug` or display name; passing a slug like `antler` returns 404. To look up a company by name or slug, use `GET /v1/companies`, `POST /v1/companies/search`, or `POST /v1/companies/find-or-create` and read the returned `id`." }, "required": true, "description": "The company's opaque object `id`: the `id` field returned by the company endpoints (e.g. `p17xq4c2b9r5gz3e8j0r6t4k7m2n9d5w`). This is NOT the `slug` or display name; passing a slug like `antler` returns 404. To look up a company by name or slug, use `GET /v1/companies`, `POST /v1/companies/search`, or `POST /v1/companies/find-or-create` and read the returned `id`.", "example": "p17xq4c2b9r5gz3e8j0r6t4k7m2n9d5w", "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateCompanyBody" } } } }, "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Company" } } } }, "400": { "description": "The request was malformed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Company not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Another company already uses the same website domain or name.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Companies" ], "operationId": "updateCompany" }, "delete": { "summary": "Delete a company", "description": "Permanently deletes a company and cascades to delete every job attached to it (along with each job’s child records). It cannot be undone.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The company's opaque object `id`: the `id` field returned by the company endpoints (e.g. `p17xq4c2b9r5gz3e8j0r6t4k7m2n9d5w`). This is NOT the `slug` or display name; passing a slug like `antler` returns 404. To look up a company by name or slug, use `GET /v1/companies`, `POST /v1/companies/search`, or `POST /v1/companies/find-or-create` and read the returned `id`." }, "required": true, "description": "The company's opaque object `id`: the `id` field returned by the company endpoints (e.g. `p17xq4c2b9r5gz3e8j0r6t4k7m2n9d5w`). This is NOT the `slug` or display name; passing a slug like `antler` returns 404. To look up a company by name or slug, use `GET /v1/companies`, `POST /v1/companies/search`, or `POST /v1/companies/find-or-create` and read the returned `id`.", "example": "p17xq4c2b9r5gz3e8j0r6t4k7m2n9d5w", "name": "id", "in": "path" } ], "responses": { "204": { "description": "Successful response." }, "404": { "description": "Company not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Companies" ], "operationId": "deleteCompany" } }, "/companies/{id}/jobs": { "get": { "summary": "List jobs at a company", "description": "Returns a list of jobs belonging to the specified company. The jobs are returned sorted by creation date, with the most recently created jobs appearing first.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The company's opaque object `id`: the `id` field returned by the company endpoints (e.g. `p17xq4c2b9r5gz3e8j0r6t4k7m2n9d5w`). This is NOT the `slug` or display name; passing a slug like `antler` returns 404. To look up a company by name or slug, use `GET /v1/companies`, `POST /v1/companies/search`, or `POST /v1/companies/find-or-create` and read the returned `id`." }, "required": true, "description": "The company's opaque object `id`: the `id` field returned by the company endpoints (e.g. `p17xq4c2b9r5gz3e8j0r6t4k7m2n9d5w`). This is NOT the `slug` or display name; passing a slug like `antler` returns 404. To look up a company by name or slug, use `GET /v1/companies`, `POST /v1/companies/search`, or `POST /v1/companies/find-or-create` and read the returned `id`.", "example": "p17xq4c2b9r5gz3e8j0r6t4k7m2n9d5w", "name": "id", "in": "path" }, { "schema": { "type": "string", "minLength": 1, "description": "An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results." }, "required": false, "description": "An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results.", "name": "cursor", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "description": "A limit on the number of objects to be returned. Limit can range between 1 and 100." }, "required": false, "description": "A limit on the number of objects to be returned. Limit can range between 1 and 100.", "example": 20, "name": "limit", "in": "query" }, { "schema": { "type": "string", "enum": [ "draft", "published", "expired", "archived" ], "description": "Only return jobs matching the given status. One of `draft`, `published`, `expired`, or `archived`." }, "required": false, "description": "Only return jobs matching the given status. One of `draft`, `published`, `expired`, or `archived`.", "example": "published", "name": "status", "in": "query" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/companies/{id}/jobs" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "nullable": true } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "404": { "description": "Company not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Companies" ], "operationId": "listCompanyJobs" } }, "/companies/{id}/logo": { "post": { "summary": "Upload a company logo", "description": "Uploads a logo for the company as a multipart form with a single `file` part. Accepts PNG, JPEG, WebP, and GIF up to 5 MB. Replaces the previous logo when one exists.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The company's opaque object `id`: the `id` field returned by the company endpoints (e.g. `p17xq4c2b9r5gz3e8j0r6t4k7m2n9d5w`). This is NOT the `slug` or display name; passing a slug like `antler` returns 404. To look up a company by name or slug, use `GET /v1/companies`, `POST /v1/companies/search`, or `POST /v1/companies/find-or-create` and read the returned `id`." }, "required": true, "description": "The company's opaque object `id`: the `id` field returned by the company endpoints (e.g. `p17xq4c2b9r5gz3e8j0r6t4k7m2n9d5w`). This is NOT the `slug` or display name; passing a slug like `antler` returns 404. To look up a company by name or slug, use `GET /v1/companies`, `POST /v1/companies/search`, or `POST /v1/companies/find-or-create` and read the returned `id`.", "example": "p17xq4c2b9r5gz3e8j0r6t4k7m2n9d5w", "name": "id", "in": "path" } ], "requestBody": { "content": { "multipart/form-data": { "schema": { "type": "object", "properties": { "file": { "type": "string", "format": "binary" } }, "required": [ "file" ] } } } }, "responses": { "201": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Company" } } } }, "400": { "description": "The request was malformed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Company not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "413": { "description": "The uploaded file exceeded the 5 MB size limit.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "415": { "description": "The uploaded file's MIME type is not supported.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Companies" ], "operationId": "uploadCompanyLogo" }, "delete": { "summary": "Delete a company logo", "description": "Removes the logo from the company and deletes the underlying file. Returns 404 if the company has no logo set.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The company's opaque object `id`: the `id` field returned by the company endpoints (e.g. `p17xq4c2b9r5gz3e8j0r6t4k7m2n9d5w`). This is NOT the `slug` or display name; passing a slug like `antler` returns 404. To look up a company by name or slug, use `GET /v1/companies`, `POST /v1/companies/search`, or `POST /v1/companies/find-or-create` and read the returned `id`." }, "required": true, "description": "The company's opaque object `id`: the `id` field returned by the company endpoints (e.g. `p17xq4c2b9r5gz3e8j0r6t4k7m2n9d5w`). This is NOT the `slug` or display name; passing a slug like `antler` returns 404. To look up a company by name or slug, use `GET /v1/companies`, `POST /v1/companies/search`, or `POST /v1/companies/find-or-create` and read the returned `id`.", "example": "p17xq4c2b9r5gz3e8j0r6t4k7m2n9d5w", "name": "id", "in": "path" } ], "responses": { "204": { "description": "Successful response." }, "404": { "description": "Company not found, or the company has no logo to remove.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Companies" ], "operationId": "deleteCompanyLogo" } }, "/coupons": { "get": { "summary": "List coupons", "description": "List the Board's coupons. Provider configuration and identifiers remain private.", "responses": { "200": { "description": "Coupons.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/coupons" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Coupon" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Coupons" ], "operationId": "listCoupons" }, "post": { "summary": "Create a coupon", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateCouponBody" } } } }, "responses": { "201": { "description": "Created coupon.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Coupon" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Coupons" ], "operationId": "createCoupon" } }, "/coupons/promotion-codes/{id}/archive": { "post": { "summary": "Archive a promotion code", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The promotion code id." }, "required": true, "description": "The promotion code id.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Archived promotion code.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PromotionCode" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Coupons" ], "operationId": "archivePromotionCode" } }, "/coupons/{id}": { "get": { "summary": "Get a coupon", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The coupon id." }, "required": true, "description": "The coupon id.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "The coupon.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Coupon" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Coupons" ], "operationId": "getCoupon" }, "patch": { "summary": "Rename a coupon", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The coupon id." }, "required": true, "description": "The coupon id.", "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RenameCouponBody" } } } }, "responses": { "200": { "description": "Updated coupon.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Coupon" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Coupons" ], "operationId": "updateCoupon" }, "delete": { "summary": "Delete a coupon", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The coupon id." }, "required": true, "description": "The coupon id.", "name": "id", "in": "path" } ], "responses": { "204": { "description": "Deleted." }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Coupons" ], "operationId": "deleteCoupon" } }, "/coupons/{id}/promotion-codes": { "post": { "summary": "Create a promotion code", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The coupon id." }, "required": true, "description": "The coupon id.", "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreatePromotionCodeBody" } } } }, "responses": { "201": { "description": "Created promotion code.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PromotionCode" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Coupons" ], "operationId": "createCouponPromotionCode" } }, "/domains": { "get": { "summary": "List custom domains", "description": "Returns the custom domains registered for your board.", "parameters": [ { "schema": { "type": "string", "minLength": 1 }, "required": false, "name": "cursor", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 50 }, "required": false, "name": "limit", "in": "query" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/domains" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Domain" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "400": { "description": "The pagination cursor is invalid.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Domains" ], "operationId": "listDomains" }, "post": { "summary": "Add a custom domain", "description": "Registers a custom domain and returns the DNS verification token and instructions.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateDomainBody" } } } }, "responses": { "201": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Domain" } } } }, "400": { "description": "The hostname is invalid.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The hostname is already registered.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Domains" ], "operationId": "createDomain" } }, "/domains/{id}": { "get": { "summary": "Retrieve a custom domain", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The custom domain ID." }, "required": true, "description": "The custom domain ID.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Domain" } } } }, "404": { "description": "Domain not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Domains" ], "operationId": "getDomain" }, "delete": { "summary": "Delete a custom domain", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The custom domain ID." }, "required": true, "description": "The custom domain ID.", "name": "id", "in": "path" } ], "responses": { "204": { "description": "Successful response." }, "404": { "description": "Domain not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Domains" ], "operationId": "deleteDomain" } }, "/domains/{id}/verify": { "post": { "summary": "Verify a custom domain", "description": "Starts an asynchronous `domains.verify` operation for the custom domain.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The custom domain ID." }, "required": true, "description": "The custom domain ID.", "name": "id", "in": "path" } ], "responses": { "202": { "description": "Verification operation started.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OperationResource" } } } }, "404": { "description": "Domain not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Domains" ], "operationId": "verifyDomain" } }, "/employer-subscriptions": { "get": { "summary": "List employer subscriptions", "description": "List employer subscriptions on the tenant's board with hydrated plan and company names.", "parameters": [ { "schema": { "type": "string", "minLength": 1 }, "required": false, "name": "cursor", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 100 }, "required": false, "name": "limit", "in": "query" }, { "schema": { "type": "string", "minLength": 1 }, "required": false, "name": "status", "in": "query" }, { "schema": { "type": "string", "minLength": 1 }, "required": false, "name": "companyId", "in": "query" } ], "responses": { "200": { "description": "Paginated employer subscriptions.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/employer-subscriptions" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/EmployerSubscription" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Employer subscriptions" ], "operationId": "listEmployerSubscriptions" } }, "/employer-subscriptions/{id}": { "get": { "summary": "Get an employer subscription", "description": "Fetch one employer subscription by id. Cross-tenant ids return 404.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The employer subscription ID." }, "required": true, "description": "The employer subscription ID.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "The employer subscription.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EmployerSubscription" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Employer subscriptions" ], "operationId": "getEmployerSubscription" } }, "/employers": { "get": { "summary": "List employers", "description": "Returns the employers (board users with role `employer`) of the authenticated account, with their approved company memberships and pending claims. Employers with no membership or claim are omitted. Requires `employers.read`.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "Pagination cursor." }, "required": false, "description": "Pagination cursor.", "name": "cursor", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Page size (1–100, default 50)." }, "required": false, "description": "Page size (1–100, default 50).", "name": "limit", "in": "query" }, { "schema": { "type": "string", "minLength": 1, "description": "Case-insensitive substring match on the employer email or display name." }, "required": false, "description": "Case-insensitive substring match on the employer email or display name.", "name": "search", "in": "query" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/employers" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Employer" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Employers" ], "operationId": "listEmployers" } }, "/employers/claims": { "get": { "summary": "List company claims", "description": "Returns company claims (employer memberships awaiting approval) on the account. Defaults to `status=pending`; pass `status` to inspect approved/rejected history. Requires `employers.read`.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "Pagination cursor." }, "required": false, "description": "Pagination cursor.", "name": "cursor", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Page size (1–100, default 50)." }, "required": false, "description": "Page size (1–100, default 50).", "name": "limit", "in": "query" }, { "schema": { "type": "string", "enum": [ "pending", "approved", "rejected" ], "description": "Filter claims by status. Defaults to `pending`." }, "required": false, "description": "Filter claims by status. Defaults to `pending`.", "name": "status", "in": "query" }, { "schema": { "type": "string", "minLength": 1, "description": "Filter to a single company id." }, "required": false, "description": "Filter to a single company id.", "name": "companyId", "in": "query" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/employers/claims" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/CompanyClaim" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Employers" ], "operationId": "listEmployersClaims" } }, "/employers/claims/{id}/approve": { "post": { "summary": "Approve a company claim", "description": "Approve a pending company claim: the employer gains access to post for that company. Idempotent: re-approving an already-approved claim returns it unchanged. Requires `employers.manage`.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The company claim id." }, "required": true, "description": "The company claim id.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CompanyClaim" } } } }, "404": { "description": "Claim not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The claim has already been resolved.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Employers" ], "operationId": "approveEmployersClaim" } }, "/employers/claims/{id}/reject": { "post": { "summary": "Reject a company claim", "description": "Reject a pending company claim. Idempotent: re-rejecting an already-rejected claim returns it unchanged. Requires `employers.manage`.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The company claim id." }, "required": true, "description": "The company claim id.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CompanyClaim" } } } }, "404": { "description": "Claim not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The claim has already been resolved.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Employers" ], "operationId": "rejectEmployersClaim" } }, "/employers/export": { "get": { "summary": "Export employers", "description": "Exports the account’s employers. `format=json` returns an inline list of export rows (max 10,000; fields mirror the CSV columns, camelCase). `format=csv` (default) returns `202` with an `exports.generate` operation — poll it, then download the CSV from `GET /v1/operations/{id}/download` once it succeeds. Requires `employers.read`.", "parameters": [ { "schema": { "type": "string", "enum": [ "csv", "json" ], "default": "csv", "description": "Export format. `json` streams an inline list of employer export rows (capped at 10,000 rows); `csv` (default) starts an async `exports.generate` operation." }, "required": false, "description": "Export format. `json` streams an inline list of employer export rows (capped at 10,000 rows); `csv` (default) starts an async `exports.generate` operation.", "name": "format", "in": "query" } ], "responses": { "200": { "description": "Inline JSON export (`format=json`).", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/employers/export" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/ExportRow" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "202": { "description": "An `exports.generate` operation was started (`format=csv`). Poll the operation; once it succeeds, download the CSV from `GET /v1/operations/{id}/download`.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OperationResource" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Employers" ], "operationId": "exportEmployers" } }, "/employers/memberships": { "get": { "summary": "List employer company memberships", "description": "Returns all employer↔company memberships on the account, across companies. Filter by `status` and a single `companyId`. Requires `employers.read`.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "Pagination cursor." }, "required": false, "description": "Pagination cursor.", "name": "cursor", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Page size (1–100, default 50)." }, "required": false, "description": "Page size (1–100, default 50).", "name": "limit", "in": "query" }, { "schema": { "type": "string", "enum": [ "pending", "approved", "rejected" ], "description": "Filter memberships by status." }, "required": false, "description": "Filter memberships by status.", "name": "status", "in": "query" }, { "schema": { "type": "string", "minLength": 1, "description": "Filter to a single company id." }, "required": false, "description": "Filter to a single company id.", "name": "companyId", "in": "query" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/employers/memberships" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/EmployerMembership" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Employers" ], "operationId": "listEmployersMemberships" } }, "/employers/memberships/{id}": { "get": { "summary": "Retrieve an employer company membership", "description": "Returns one employer↔company membership on the account. Requires `employers.read`.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The membership id." }, "required": true, "description": "The membership id.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EmployerMembership" } } } }, "404": { "description": "Membership not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Employers" ], "operationId": "getEmployersMembership" } }, "/employers/{id}": { "get": { "summary": "Get an employer", "description": "Returns a single employer with their company memberships and pending claims. Requires `employers.read`.", "parameters": [ { "schema": { "type": "string", "description": "The employer id." }, "required": true, "description": "The employer id.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Employer" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Employers" ], "operationId": "getEmployer" }, "delete": { "summary": "Delete an employer", "description": "Permanently erases an employer and all associated data, including company memberships/claims (GDPR cascade). Always asynchronous: returns `202` with an `employers.remove` operation. Poll it; the terminal result carries `{ employerId, deletedResumes, deletedSavedJobs, deletedAlerts, deletedSessions, deletedMemberships }`. Requires `employers.manage`.", "parameters": [ { "schema": { "type": "string", "description": "The employer id." }, "required": true, "description": "The employer id.", "name": "id", "in": "path" } ], "responses": { "202": { "description": "Deletion operation accepted.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OperationResource" } } } }, "404": { "description": "Employer not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Employers" ], "operationId": "deleteEmployer" } }, "/imports": { "get": { "summary": "List import batches", "description": "Returns your import batches, most recent first. Filter by status and creation-time range.", "parameters": [ { "schema": { "type": "string", "minLength": 1 }, "required": false, "name": "cursor", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 50 }, "required": false, "name": "limit", "in": "query" }, { "schema": { "type": "string", "enum": [ "pending", "processing", "completed", "partial", "failed" ], "description": "Filter by batch status (single value)." }, "required": false, "description": "Filter by batch status (single value).", "name": "status", "in": "query" }, { "schema": { "type": "string", "format": "date-time", "description": "Only batches created at or after this ISO 8601 timestamp." }, "required": false, "description": "Only batches created at or after this ISO 8601 timestamp.", "name": "from", "in": "query" }, { "schema": { "type": "string", "format": "date-time", "description": "Only batches created at or before this ISO 8601 timestamp." }, "required": false, "description": "Only batches created at or before this ISO 8601 timestamp.", "name": "to", "in": "query" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/imports" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Import" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "400": { "description": "The pagination cursor or query is invalid.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Imports" ], "operationId": "listImports" }, "post": { "summary": "Upload a file and start discovery", "description": "Uploads a CSV (multipart/form-data `file`) and starts the async `imports.parse` discovery operation. Only `sourceFormat=csv` is supported in v1.", "requestBody": { "required": true, "content": { "multipart/form-data": { "schema": { "type": "object", "properties": { "file": { "type": "string", "format": "binary", "description": "The CSV file to discover and import." }, "sourceFormat": { "type": "string", "enum": [ "csv" ], "description": "Optional source format. Defaults to `csv`." } }, "required": [ "file" ] } } } }, "responses": { "202": { "description": "Discovery operation started.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OperationResource" } } } }, "400": { "description": "Unsupported source format or invalid request.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "413": { "description": "The file exceeds the maximum size.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "415": { "description": "Unsupported file type.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "description": "Daily import limit reached.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Imports" ], "operationId": "createImport" } }, "/imports/quota": { "get": { "summary": "Retrieve import quota", "description": "Your account's daily import usage and reset boundary.", "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ImportQuota" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Imports" ], "operationId": "getImportsQuota" } }, "/imports/{id}": { "get": { "summary": "Retrieve an import batch", "description": "Returns one import batch including live status, row errors, and the proposed mapping.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The import batch ID." }, "required": true, "description": "The import batch ID.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ImportDetail" } } } }, "404": { "description": "Import not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Imports" ], "operationId": "getImport" } }, "/imports/{id}/cancel": { "post": { "summary": "Cancel an import batch", "description": "Cancels a pending or running import batch. Rows already written remain.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The import batch ID." }, "required": true, "description": "The import batch ID.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "The updated import batch.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ImportDetail" } } } }, "404": { "description": "Import not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Import is already in a terminal state.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Imports" ], "operationId": "cancelImport" } }, "/imports/{id}/confirm": { "post": { "summary": "Confirm the mapping and start execution", "description": "Confirms the proposed (or an inline) mapping and starts the async `imports.confirm` execution operation.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The import batch ID." }, "required": true, "description": "The import batch ID.", "name": "id", "in": "path" } ], "requestBody": { "required": false, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ConfirmImportBody" } } } }, "responses": { "202": { "description": "Execution operation started.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OperationResource" } } } }, "400": { "description": "No mapping available.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Import not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Import already confirmed or terminal.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Imports" ], "operationId": "confirmImport" } }, "/integrations/indexing": { "get": { "summary": "Retrieve the indexing configuration", "description": "Returns the account's Google Indexing + IndexNow configuration. Always returns a config (indexing reads as disabled when never provisioned).", "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IndexingConfig" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Integrations" ], "operationId": "getIntegrationsIndexing" } }, "/integrations/indexing/toggle-indexnow": { "post": { "summary": "Toggle IndexNow", "description": "Enables or disables IndexNow (Bing/Yandex instant indexing). Enabling is refused (409) while board password protection is active.", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IndexingToggleBody" } } } }, "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IndexingConfig" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Integrations" ], "operationId": "toggleIndexNow" } }, "/integrations/reporting": { "get": { "summary": "List reporting integrations", "description": "Returns normalized connection state for the Board's reporting integrations. Provider identifiers, grants, credentials, settings, and collector telemetry are not returned.", "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/integrations/reporting" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/ReportingIntegration" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Integrations" ], "operationId": "listIntegrationsReporting" } }, "/integrations/reporting/{provider}": { "get": { "summary": "Retrieve a reporting integration", "description": "Returns a single reporting integration by provider key, or 404 if the account has none for that provider.", "parameters": [ { "schema": { "type": "string", "enum": [ "search_console", "adsense", "tinybird", "stripe", "google_analytics" ], "description": "The reporting provider key." }, "required": true, "description": "The reporting provider key.", "name": "provider", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReportingIntegration" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Integrations" ], "operationId": "getIntegrationsReporting" }, "patch": { "summary": "Enable or disable a reporting integration", "description": "Pauses or resumes collection for an existing integration without disconnecting it.", "parameters": [ { "schema": { "type": "string", "enum": [ "search_console", "adsense", "tinybird", "stripe", "google_analytics" ], "description": "The reporting provider key." }, "required": true, "description": "The reporting provider key.", "name": "provider", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PatchReportingIntegrationBody" } } } }, "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReportingIntegration" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Integrations" ], "operationId": "updateIntegrationsReporting" }, "delete": { "summary": "Disconnect a reporting integration", "description": "Deletes the integration. Stripe is managed from Monetization settings and cannot be disconnected here (409).", "parameters": [ { "schema": { "type": "string", "enum": [ "search_console", "adsense", "tinybird", "stripe", "google_analytics" ], "description": "The reporting provider key." }, "required": true, "description": "The reporting provider key.", "name": "provider", "in": "path" } ], "responses": { "204": { "description": "The integration was disconnected." }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Integrations" ], "operationId": "deleteIntegrationsReporting" } }, "/integrations/reporting/{provider}/connect": { "post": { "summary": "Connect a reporting integration", "description": "Starts the connection flow. Some providers return a hosted authorization URL, some connect immediately, and payment reporting returns the Board monetization-settings URL. Provider credentials and configuration are never returned.", "parameters": [ { "schema": { "type": "string", "enum": [ "search_console", "adsense", "tinybird", "stripe", "google_analytics" ], "description": "The reporting provider key." }, "required": true, "description": "The reporting provider key.", "name": "provider", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReportingConnect" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Integrations" ], "operationId": "connectIntegrationsReporting" } }, "/invitations": { "get": { "summary": "List invitations", "description": "Returns the invitations for the authenticated account, optionally filtered by status. The accept `token` is never included in list responses.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "Pagination cursor." }, "required": false, "description": "Pagination cursor.", "name": "cursor", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Page size (1–100, default 50)." }, "required": false, "description": "Page size (1–100, default 50).", "name": "limit", "in": "query" }, { "schema": { "type": "string", "enum": [ "pending", "expired", "accepted", "declined" ], "description": "Filter the returned invitations by status." }, "required": false, "description": "Filter the returned invitations by status.", "name": "status", "in": "query" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/invitations" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Invitation" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Invitations" ], "operationId": "listInvitations" }, "post": { "summary": "Create an invitation", "description": "Invites a new member by email and sends the invitation email. The response includes the accept `token` and `acceptUrl` (returned only on create and renew).", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateInvitationBody" } } } }, "responses": { "201": { "description": "The invitation was created.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/InvitationWithToken" } } } }, "403": { "description": "Team seat limit reached.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The email already belongs to a member.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Invitations" ], "operationId": "createInvitation" } }, "/invitations/{id}": { "patch": { "summary": "Update an invitation", "description": "Changes a pending invitation's role.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The invitation ID." }, "required": true, "description": "The invitation ID.", "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateInvitationBody" } } } }, "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Invitation" } } } }, "404": { "description": "Invitation not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The invitation is no longer pending.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Invitations" ], "operationId": "updateInvitation" }, "delete": { "summary": "Delete an invitation", "description": "Cancels a pending invitation.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The invitation ID." }, "required": true, "description": "The invitation ID.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "The invitation was cancelled." }, "404": { "description": "Invitation not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Invitations" ], "operationId": "deleteInvitation" } }, "/invitations/{id}/accept": { "post": { "summary": "Accept an invitation", "description": "Accepts an invitation by its token (passed as the path segment). Session-authenticated only. The accepting user joins the invitation’s account. The caller’s email must match the invitation.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The invitation ID." }, "required": true, "description": "The invitation ID.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "The invitation was accepted." }, "403": { "description": "The email does not match the invitation.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Invitation not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The invitation is no longer pending.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "410": { "description": "The invitation has expired.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Invitations" ], "operationId": "acceptInvitation" } }, "/invitations/{id}/renew": { "post": { "summary": "Renew an invitation", "description": "Rotates the accept token and extends the expiry by 7 days. The response includes the new token and `acceptUrl`.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The invitation ID." }, "required": true, "description": "The invitation ID.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/InvitationWithToken" } } } }, "404": { "description": "Invitation not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "An already-accepted invitation cannot be renewed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Invitations" ], "operationId": "renewInvitation" } }, "/jobs": { "get": { "summary": "List jobs", "description": "Returns a list of your jobs. The jobs are returned sorted by creation date, with the most recently created jobs appearing first.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results." }, "required": false, "description": "An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results.", "name": "cursor", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "description": "A limit on the number of objects to be returned. Limit can range between 1 and 100." }, "required": false, "description": "A limit on the number of objects to be returned. Limit can range between 1 and 100.", "example": 20, "name": "limit", "in": "query" }, { "schema": { "type": "string", "enum": [ "draft", "published", "expired", "archived" ], "description": "Only return jobs matching the given status. One of `draft`, `published`, `expired`, or `archived`." }, "required": false, "description": "Only return jobs matching the given status. One of `draft`, `published`, `expired`, or `archived`.", "example": "published", "name": "status", "in": "query" }, { "schema": { "type": "string", "minLength": 1, "description": "Only return jobs at the company with the given ID." }, "required": false, "description": "Only return jobs at the company with the given ID.", "name": "companyId", "in": "query" }, { "schema": { "type": "string", "minLength": 1, "maxLength": 2048, "description": "Only return jobs matching this application URL. URLs are normalized server-side (casing, tracking params, etc.) so equivalent links match. Useful for deduplication lookups." }, "required": false, "description": "Only return jobs matching this application URL. URLs are normalized server-side (casing, tracking params, etc.) so equivalent links match. Useful for deduplication lookups.", "name": "applicationUrl", "in": "query" }, { "schema": { "type": "string", "minLength": 1, "maxLength": 255, "description": "Only return jobs with this `externalId`. Useful for deduplication lookups when reposting from an ATS." }, "required": false, "description": "Only return jobs with this `externalId`. Useful for deduplication lookups when reposting from an ATS.", "name": "externalId", "in": "query" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/jobs" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/JobSummary" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "400": { "description": "The request was malformed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Jobs" ], "operationId": "listJobs" }, "post": { "summary": "Create a job", "description": "Creates a new job in `draft` status. The request is idempotent when an `Idempotency-Key` header is supplied. Reposts of existing jobs return 409 `jobs_already_exists` with the matching job ID.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateJobBody" } } } }, "responses": { "201": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Job" } } } }, "400": { "description": "The request was malformed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "The supplied company does not exist or is not accessible.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "A job with the same `applicationUrl`, `externalId`, or content already exists on your account. The matching job ID is returned in `details.existing_job_id`.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Jobs" ], "operationId": "createJob" } }, "/jobs/batch": { "post": { "summary": "Run a batch of job operations", "description": "Runs up to 100 job operations in a single request. Supported sub-operations are create (`POST`), update (`PATCH`), delete (`DELETE`), publish, pause, expire, and duplicate. Each sub-operation runs independently; the response is HTTP 200 for any well-formed batch, and the per-operation outcome is reported on each entry of the `data` array.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchRequestBody" } } } }, "responses": { "200": { "description": "Successful response. Inspect each entry of the `data` array for the per-sub-operation status.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "batch_result" ] }, "data": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "status": { "type": "number" }, "data": { "nullable": true }, "error": { "type": "object", "properties": { "code": { "type": "string" }, "message": { "type": "string" }, "details": { "nullable": true } }, "required": [ "code", "message" ] } }, "required": [ "id", "status" ] } } }, "required": [ "object", "data" ] } } } }, "400": { "description": "The batch was malformed (too many sub-operations, duplicate sub-operation IDs, or invalid sub-operation shapes).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "413": { "description": "The request body exceeded 5 MB.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Jobs" ], "operationId": "batchJobs" } }, "/jobs/export": { "get": { "summary": "Export jobs", "description": "Exports the account’s jobs. `format=json` returns an inline list of export rows (max 10,000; fields mirror the CSV columns, camelCase). `format=csv` (default) returns `202` with an `exports.generate` operation — poll it, then download the CSV from `GET /v1/operations/{id}/download` once it succeeds. Requires `jobs.read`.", "parameters": [ { "schema": { "type": "string", "enum": [ "csv", "json" ], "default": "csv", "description": "Export format. `json` streams an inline list of job export rows (capped at 10,000 rows); `csv` (default) starts an async `exports.generate` operation." }, "required": false, "description": "Export format. `json` streams an inline list of job export rows (capped at 10,000 rows); `csv` (default) starts an async `exports.generate` operation.", "name": "format", "in": "query" } ], "responses": { "200": { "description": "Inline JSON export (`format=json`).", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/jobs/export" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/ExportRow" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "202": { "description": "An `exports.generate` operation was started (`format=csv`). Poll the operation; once it succeeds, download the CSV from `GET /v1/operations/{id}/download`.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OperationResource" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Jobs" ], "operationId": "exportJobs" } }, "/jobs/search": { "post": { "summary": "Search jobs", "description": "Searches your jobs using a free-text query and faceted filters. Results are returned sorted by creation date, with the most recently created jobs appearing first. Multi-value filters match jobs in any of the supplied values; range filters accept `gte` and `lte` bounds. Each filter array accepts up to 10 values.", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SearchJobsBody" } } } }, "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "search_result" ] }, "url": { "type": "string", "example": "/v1/jobs/search" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/JobSummary" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "400": { "description": "The request was malformed, or a filter array exceeded the per-array cap.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "A supplied `companyId` filter does not exist or is not accessible.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Jobs" ], "operationId": "searchJobs" } }, "/jobs/{id}": { "get": { "summary": "Retrieve a job", "description": "Retrieves the details of an existing job. You only need to supply the unique job ID that was returned upon job creation.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The job's opaque object `id`: the `id` field returned by the job endpoints (e.g. `j8k2q7d4b9r3m6x0p5t1v7w2y9z4c8n3`). This is NOT the `slug` or title; passing a slug like `senior-backend-engineer` returns 404. To look up a job by title or slug, use `GET /v1/jobs` or `POST /v1/jobs/search` and read the returned `id`." }, "required": true, "description": "The job's opaque object `id`: the `id` field returned by the job endpoints (e.g. `j8k2q7d4b9r3m6x0p5t1v7w2y9z4c8n3`). This is NOT the `slug` or title; passing a slug like `senior-backend-engineer` returns 404. To look up a job by title or slug, use `GET /v1/jobs` or `POST /v1/jobs/search` and read the returned `id`.", "example": "j8k2q7d4b9r3m6x0p5t1v7w2y9z4c8n3", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Job" } } } }, "404": { "description": "Job not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Jobs" ], "operationId": "getJob" }, "patch": { "summary": "Update a job", "description": "Updates the specified job by setting the values of the parameters passed. Any parameters not provided will be left unchanged. Pass `expiresAt: null` to clear the expiry.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The job's opaque object `id`: the `id` field returned by the job endpoints (e.g. `j8k2q7d4b9r3m6x0p5t1v7w2y9z4c8n3`). This is NOT the `slug` or title; passing a slug like `senior-backend-engineer` returns 404. To look up a job by title or slug, use `GET /v1/jobs` or `POST /v1/jobs/search` and read the returned `id`." }, "required": true, "description": "The job's opaque object `id`: the `id` field returned by the job endpoints (e.g. `j8k2q7d4b9r3m6x0p5t1v7w2y9z4c8n3`). This is NOT the `slug` or title; passing a slug like `senior-backend-engineer` returns 404. To look up a job by title or slug, use `GET /v1/jobs` or `POST /v1/jobs/search` and read the returned `id`.", "example": "j8k2q7d4b9r3m6x0p5t1v7w2y9z4c8n3", "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateJobBody" } } } }, "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Job" } } } }, "400": { "description": "The request was malformed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Job not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Jobs" ], "operationId": "updateJob" }, "delete": { "summary": "Delete a job", "description": "Permanently deletes a job. It cannot be undone. Saved jobs, orders, and any associated search-index entries are also removed.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The job's opaque object `id`: the `id` field returned by the job endpoints (e.g. `j8k2q7d4b9r3m6x0p5t1v7w2y9z4c8n3`). This is NOT the `slug` or title; passing a slug like `senior-backend-engineer` returns 404. To look up a job by title or slug, use `GET /v1/jobs` or `POST /v1/jobs/search` and read the returned `id`." }, "required": true, "description": "The job's opaque object `id`: the `id` field returned by the job endpoints (e.g. `j8k2q7d4b9r3m6x0p5t1v7w2y9z4c8n3`). This is NOT the `slug` or title; passing a slug like `senior-backend-engineer` returns 404. To look up a job by title or slug, use `GET /v1/jobs` or `POST /v1/jobs/search` and read the returned `id`.", "example": "j8k2q7d4b9r3m6x0p5t1v7w2y9z4c8n3", "name": "id", "in": "path" } ], "responses": { "204": { "description": "Successful response." }, "404": { "description": "Job not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Jobs" ], "operationId": "deleteJob" } }, "/jobs/{id}/duplicate": { "post": { "summary": "Duplicate a job", "description": "Creates a new draft job by copying the fields of an existing job. The slug of the new job is generated with a `copy-of-` prefix to keep it unique.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The job's opaque object `id`: the `id` field returned by the job endpoints (e.g. `j8k2q7d4b9r3m6x0p5t1v7w2y9z4c8n3`). This is NOT the `slug` or title; passing a slug like `senior-backend-engineer` returns 404. To look up a job by title or slug, use `GET /v1/jobs` or `POST /v1/jobs/search` and read the returned `id`." }, "required": true, "description": "The job's opaque object `id`: the `id` field returned by the job endpoints (e.g. `j8k2q7d4b9r3m6x0p5t1v7w2y9z4c8n3`). This is NOT the `slug` or title; passing a slug like `senior-backend-engineer` returns 404. To look up a job by title or slug, use `GET /v1/jobs` or `POST /v1/jobs/search` and read the returned `id`.", "example": "j8k2q7d4b9r3m6x0p5t1v7w2y9z4c8n3", "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DuplicateJobBody" } } } }, "responses": { "201": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Job" } } } }, "404": { "description": "Job not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Jobs" ], "operationId": "duplicateJob" } }, "/jobs/{id}/expire": { "post": { "summary": "Expire a job", "description": "Marks a published job as expired. The `status` is set to `expired` and `expiresAt` is set to the current time. Expired jobs are removed from the public board and can be reopened by publishing them again.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The job's opaque object `id`: the `id` field returned by the job endpoints (e.g. `j8k2q7d4b9r3m6x0p5t1v7w2y9z4c8n3`). This is NOT the `slug` or title; passing a slug like `senior-backend-engineer` returns 404. To look up a job by title or slug, use `GET /v1/jobs` or `POST /v1/jobs/search` and read the returned `id`." }, "required": true, "description": "The job's opaque object `id`: the `id` field returned by the job endpoints (e.g. `j8k2q7d4b9r3m6x0p5t1v7w2y9z4c8n3`). This is NOT the `slug` or title; passing a slug like `senior-backend-engineer` returns 404. To look up a job by title or slug, use `GET /v1/jobs` or `POST /v1/jobs/search` and read the returned `id`.", "example": "j8k2q7d4b9r3m6x0p5t1v7w2y9z4c8n3", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Job" } } } }, "404": { "description": "Job not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The job is not currently published.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Jobs" ], "operationId": "expireJob" } }, "/jobs/{id}/pause": { "post": { "summary": "Pause a job", "description": "Returns a published job to draft status. The job is removed from the public board until it is published again.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The job's opaque object `id`: the `id` field returned by the job endpoints (e.g. `j8k2q7d4b9r3m6x0p5t1v7w2y9z4c8n3`). This is NOT the `slug` or title; passing a slug like `senior-backend-engineer` returns 404. To look up a job by title or slug, use `GET /v1/jobs` or `POST /v1/jobs/search` and read the returned `id`." }, "required": true, "description": "The job's opaque object `id`: the `id` field returned by the job endpoints (e.g. `j8k2q7d4b9r3m6x0p5t1v7w2y9z4c8n3`). This is NOT the `slug` or title; passing a slug like `senior-backend-engineer` returns 404. To look up a job by title or slug, use `GET /v1/jobs` or `POST /v1/jobs/search` and read the returned `id`.", "example": "j8k2q7d4b9r3m6x0p5t1v7w2y9z4c8n3", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Job" } } } }, "404": { "description": "Job not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The job is not currently published.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Jobs" ], "operationId": "pauseJob" } }, "/jobs/{id}/publish": { "post": { "summary": "Publish a job", "description": "Publishes a draft or expired job, making it visible on the public board. Plan and quota limits are enforced. `expiresAt` accepts an ISO 8601 string to set a new expiry, `null` to clear, or may be omitted. When omitted, a stored future expiry is preserved; a stored past expiry (e.g. set by a prior `expire` call) is cleared automatically so a republished job is never published with a stale past timestamp.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The job's opaque object `id`: the `id` field returned by the job endpoints (e.g. `j8k2q7d4b9r3m6x0p5t1v7w2y9z4c8n3`). This is NOT the `slug` or title; passing a slug like `senior-backend-engineer` returns 404. To look up a job by title or slug, use `GET /v1/jobs` or `POST /v1/jobs/search` and read the returned `id`." }, "required": true, "description": "The job's opaque object `id`: the `id` field returned by the job endpoints (e.g. `j8k2q7d4b9r3m6x0p5t1v7w2y9z4c8n3`). This is NOT the `slug` or title; passing a slug like `senior-backend-engineer` returns 404. To look up a job by title or slug, use `GET /v1/jobs` or `POST /v1/jobs/search` and read the returned `id`.", "example": "j8k2q7d4b9r3m6x0p5t1v7w2y9z4c8n3", "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PublishJobBody" } } } }, "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Job" } } } }, "404": { "description": "Job not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The job is already published, or the account's published-job quota is exhausted.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Jobs" ], "operationId": "publishJob" } }, "/me": { "get": { "summary": "Retrieve the current operator identity", "description": "Returns the Board bound to the credential, the actor type, the current live role and effective product permissions, and (for API keys and OAuth tokens) the credential scopes. Use this instead of global role or permission catalogs.", "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Operator" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Operator" ], "operationId": "getMe" } }, "/media/upload": { "post": { "summary": "Upload a media file", "description": "Uploads a file via the unified media dispatcher. Send a multipart form with `file` (binary) and `purpose` (one of `board_logo`, `board_hero`, `account_avatar`, `company_logo`, or `blog_image`). Optionally include `resourceType` and `resourceId` to bind the upload to an owning resource. The request is idempotent when an `Idempotency-Key` header is supplied.", "requestBody": { "content": { "multipart/form-data": { "schema": { "type": "object", "properties": { "file": { "type": "string", "format": "binary" }, "purpose": { "type": "string", "enum": [ "board_logo", "board_hero", "account_avatar", "company_logo", "blog_image" ] }, "resourceType": { "type": "string" }, "resourceId": { "type": "string" } }, "required": [ "file", "purpose" ] } } } }, "responses": { "201": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MediaUpload" } } } }, "400": { "description": "The `purpose` field is invalid, or the request was otherwise malformed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "description": "The caller lacks the permission required for the requested upload purpose.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "The owning resource for the upload (`resourceId`) does not exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "413": { "description": "The uploaded file exceeded the 5 MB size limit.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "415": { "description": "The uploaded file's MIME type is not supported.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "description": "Too many uploads. The limit is 30 per minute per account.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Media" ], "operationId": "uploadMedia" } }, "/media/{id}": { "get": { "summary": "Retrieve a media file", "description": "Retrieves the metadata for a media file along with a fresh signed URL valid for fifteen minutes.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The Cavuno media object's `id` returned by `POST /v1/media/upload`." }, "required": true, "description": "The Cavuno media object's `id` returned by `POST /v1/media/upload`.", "example": "media_01jxyz", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MediaGet" } } } }, "404": { "description": "Media file not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Media" ], "operationId": "getMedia" } }, "/members": { "get": { "summary": "List members", "description": "Returns the members of the authenticated account, optionally filtered by role.", "parameters": [ { "schema": { "type": "string", "enum": [ "owner", "admin", "member" ], "description": "Filter the returned members by role." }, "required": false, "description": "Filter the returned members by role.", "name": "role", "in": "query" }, { "schema": { "type": "string", "enum": [ "true", "false" ], "description": "Filter by suspension state: `true` or `false`." }, "required": false, "description": "Filter by suspension state: `true` or `false`.", "name": "suspended", "in": "query" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/members" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Member" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Members" ], "operationId": "listMembers" } }, "/members/me": { "delete": { "summary": "Leave the account", "description": "The authenticated user leaves the account. Session-authenticated only (api_key / oauth_token actors are rejected). The account owner cannot leave. Transfer ownership first.", "responses": { "200": { "description": "You left the account." }, "403": { "description": "Only a session-authenticated user can leave.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "You are not a member of this account.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The account owner cannot leave.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Members" ], "operationId": "leaveAccount" } }, "/members/transfer-ownership": { "post": { "summary": "Transfer account ownership", "description": "Transfers the primary-owner role to another member. Only the current primary owner may call this. The current owner is demoted to admin and the new owner is promoted.", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TransferOwnershipBody" } } } }, "responses": { "200": { "description": "Ownership transferred." }, "403": { "description": "Only the primary owner can transfer ownership.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "The new owner must already be a member.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Cannot transfer ownership to a suspended member.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Members" ], "operationId": "transferAccountOwnership" } }, "/members/{userId}": { "get": { "summary": "Retrieve a member", "description": "Retrieves a single member of the authenticated account by their user ID. Members of other accounts are invisible and return `members_not_found`.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The user ID of the member." }, "required": true, "description": "The user ID of the member.", "name": "userId", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Member" } } } }, "404": { "description": "Member not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Members" ], "operationId": "getMember" }, "patch": { "summary": "Update a member", "description": "Updates a member's role. The primary owner's role cannot be changed here (use transfer-ownership), and only an owner may promote a member to owner.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The user ID of the member." }, "required": true, "description": "The user ID of the member.", "name": "userId", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateMemberBody" } } } }, "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Member" } } } }, "403": { "description": "Only an owner can promote to owner.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Member not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Cannot change the primary owner role.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Members" ], "operationId": "updateMember" }, "delete": { "summary": "Remove a member", "description": "Removes a member from the account. The account owner cannot be removed. Transfer ownership first.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The user ID of the member." }, "required": true, "description": "The user ID of the member.", "name": "userId", "in": "path" } ], "responses": { "200": { "description": "The member was removed." }, "404": { "description": "Member not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Cannot remove the account owner.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Members" ], "operationId": "deleteMember" } }, "/members/{userId}/suspend": { "post": { "summary": "Suspend a member", "description": "Suspends a member: they keep their role but lose all permission evaluations. The primary owner cannot be suspended.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The user ID of the member." }, "required": true, "description": "The user ID of the member.", "name": "userId", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Member" } } } }, "404": { "description": "Member not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Cannot suspend the account primary owner.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Members" ], "operationId": "suspendMember" } }, "/members/{userId}/unsuspend": { "post": { "summary": "Unsuspend a member", "description": "Reinstates a suspended member.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The user ID of the member." }, "required": true, "description": "The user ID of the member.", "name": "userId", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Member" } } } }, "404": { "description": "Member not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Cannot suspend the account primary owner.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Members" ], "operationId": "unsuspendMember" } }, "/operations/{id}": { "get": { "summary": "Retrieve an operation", "description": "Retrieves the details of an existing operation. Operations are garbage-collected thirty days after reaching a terminal state.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "Unique identifier for the operation." }, "required": true, "description": "Unique identifier for the operation.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OperationResource" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Operations" ], "operationId": "getOperation" } }, "/operations/{id}/cancel": { "post": { "summary": "Cancel an operation", "description": "Requests cancellation of an operation. A pending operation is cancelled immediately. A running operation is flagged for cancellation; the worker observes the flag at its next checkpoint. Operations that have already reached a terminal state cannot be cancelled. Cancellation does not roll back work that has already completed.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "Unique identifier for the operation." }, "required": true, "description": "Unique identifier for the operation.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response. The returned operation reflects `cancelRequested: true`; the worker observes the flag at its next checkpoint.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OperationResource" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Operations" ], "operationId": "cancelOperation" } }, "/operations/{id}/download": { "get": { "summary": "Download an operation output", "description": "Streams the file output of a completed operation (e.g. the CSV produced by an `exports.generate` or `subscribers.export` run). Returns `200 text/csv` with a `Content-Disposition` attachment once the operation has succeeded and produced an output. Any operation that is missing, not yours, not a public kind, not yet succeeded, or has no stored output returns `404 operations_not_found`. The underlying storage URL is never exposed — the bytes are streamed through the API. Requires `operations.read`.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "Unique identifier for the operation." }, "required": true, "description": "Unique identifier for the operation.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "The operation output, streamed as a file attachment.", "content": { "text/csv": { "schema": { "type": "string", "format": "binary", "description": "CSV file bytes." } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Operations" ], "operationId": "downloadOperationOutput" } }, "/paywall": { "get": { "summary": "Get candidate paywall configuration", "description": "Return the atomic candidate-access paywall: copy, preview window, currency, and all six fixed offer keys. Missing stored offers still produce the stable six-offer resource. Requires `billing.read`. Never exposes Stripe product, price, portal, or customer identifiers.", "responses": { "200": { "description": "The candidate paywall resource.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CandidatePaywall" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Paywall" ], "operationId": "getCandidatePaywall" }, "put": { "summary": "Replace candidate paywall configuration", "description": "Atomically replace the candidate-access paywall (configuration + six offers). Matches the Board monetization form rules. Enabling requires candidate profiles, a ready hosted payment connection, and at least one nonzero enabled offer. Disabling schedules active recurring subscriptions to cancel at period end. Requires `billing.manage` and an `Idempotency-Key` header. Never accepts or returns Stripe identifiers.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PutCandidatePaywallBody" } } } }, "responses": { "200": { "description": "The replaced candidate paywall resource.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CandidatePaywall" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Paywall" ], "operationId": "replaceCandidatePaywall" } }, "/paywall/subscriptions": { "get": { "summary": "List candidate paywall subscriptions", "description": "Read-only list of candidate access subscriptions (grants) for the Board. Filter by product status and kind (`recurring` | `lifetime`). Requires `billing.read`. Never exposes Stripe customer, subscription, or checkout identifiers. There is no cancel endpoint — the ordinary UI does not provide one.", "parameters": [ { "schema": { "type": "string", "minLength": 1 }, "required": false, "name": "cursor", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 100 }, "required": false, "name": "limit", "in": "query" }, { "schema": { "type": "string", "enum": [ "pending", "active", "trialing", "expired", "past_due", "unpaid", "incomplete", "incomplete_expired", "canceled" ] }, "required": false, "name": "status", "in": "query" }, { "schema": { "type": "string", "enum": [ "recurring", "lifetime" ] }, "required": false, "name": "kind", "in": "query" } ], "responses": { "200": { "description": "Paginated candidate paywall subscriptions.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/paywall/subscriptions" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/CandidatePaywallSubscription" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Paywall" ], "operationId": "listCandidatePaywallSubscriptions" } }, "/plans": { "get": { "summary": "List employer plans", "description": "Returns the account's employer plans (the plans a board operator sells to employers), each with its single price and feature values.", "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/plans" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/AdminPlan" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Plans" ], "operationId": "listPlans" }, "post": { "summary": "Create an employer plan", "description": "Creates plan metadata only. Set the price with PUT /v1/plans/:id/price after the Board payment connection is ready.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreatePlanBody" } } } }, "responses": { "201": { "description": "Plan created.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AdminPlan" } } } }, "400": { "description": "The request was malformed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Plans" ], "operationId": "createPlan" } }, "/plans/{id}": { "get": { "summary": "Get an employer plan", "description": "Fetch one plan with its single price and feature values.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The plan ID returned by create or list endpoints." }, "required": true, "description": "The plan ID returned by create or list endpoints.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AdminPlan" } } } }, "404": { "description": "Plan not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Plans" ], "operationId": "getPlan" }, "patch": { "summary": "Update an employer plan", "description": "Patch plan metadata. Archive with `isArchived: true`; publish/unpublish with `isPublic`. There is no hard DELETE.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The plan ID returned by create or list endpoints." }, "required": true, "description": "The plan ID returned by create or list endpoints.", "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdatePlanBody" } } } }, "responses": { "200": { "description": "Updated plan.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AdminPlan" } } } }, "404": { "description": "Plan not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Plans" ], "operationId": "updatePlan" } }, "/plans/{id}/features": { "get": { "summary": "List plan feature values", "description": "Returns the feature key/value pairs assigned to the plan.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The plan ID returned by create or list endpoints." }, "required": true, "description": "The plan ID returned by create or list endpoints.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/plans/{id}/features" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/PlanFeatureValue" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "404": { "description": "Plan not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Plans" ], "operationId": "listPlanFeatures" }, "put": { "summary": "Replace plan feature values", "description": "Full-replace the typed capability values for a plan. Unknown keys and invalid values are rejected.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The plan ID returned by create or list endpoints." }, "required": true, "description": "The plan ID returned by create or list endpoints.", "name": "id", "in": "path" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetPlanFeaturesBody" } } } }, "responses": { "200": { "description": "Feature values replaced.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/plans/{id}/features" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/PlanFeatureValue" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "400": { "description": "Unknown capability key or invalid typed value.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Plan not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Plans" ], "operationId": "updatePlanFeatures" } }, "/plans/{id}/price": { "put": { "summary": "Set the plan price", "description": "Upserts the single checkout price for the plan. Requires a ready Board payment connection and an Idempotency-Key header.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The plan ID returned by create or list endpoints." }, "required": true, "description": "The plan ID returned by create or list endpoints.", "name": "id", "in": "path" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetPlanPriceBody" } } } }, "responses": { "200": { "description": "Price set and synced.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PlanPrice" } } } }, "404": { "description": "Plan not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The Board payment connection is not ready.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "502": { "description": "Price publishing failed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Plans" ], "operationId": "updatePlanPrice" } }, "/redirects": { "get": { "summary": "List redirect rules", "description": "Returns redirect rules for the authenticated account, sorted by source path. Supports cursor pagination and optional prefix search on `fromPath`.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "An opaque pagination cursor returned in the `nextCursor` field of a previous response." }, "required": false, "description": "An opaque pagination cursor returned in the `nextCursor` field of a previous response.", "name": "cursor", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "description": "A limit on the number of objects to be returned. Limit can range between 1 and 100." }, "required": false, "description": "A limit on the number of objects to be returned. Limit can range between 1 and 100.", "example": 50, "name": "limit", "in": "query" }, { "schema": { "type": "string", "minLength": 1, "description": "Prefix match against `fromPath`. Only redirects whose source path starts with this value are returned." }, "required": false, "description": "Prefix match against `fromPath`. Only redirects whose source path starts with this value are returned.", "name": "search", "in": "query" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/redirects" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Redirect" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "400": { "description": "The request was malformed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Redirects" ], "operationId": "listRedirects" }, "post": { "summary": "Create a redirect rule", "description": "Creates a redirect. The request is idempotent when an `Idempotency-Key` header is supplied.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateRedirectBody" } } } }, "responses": { "201": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Redirect" } } } }, "400": { "description": "The request was malformed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "A redirect from this path already exists.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Redirects" ], "operationId": "createRedirect" } }, "/redirects/batch": { "post": { "summary": "Run a batch of redirect operations", "description": "Runs up to 100 redirect operations in a single request, with a 5 MB request body limit. Each sub-operation runs independently. Idempotency keys are honored on the batch itself, not on individual sub-operations.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RedirectsBatchRequest" } } } }, "responses": { "200": { "description": "Successful response. Inspect each entry of the `data` array for the per-sub-operation status.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "batch_result" ] }, "data": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "status": { "type": "number" }, "data": { "nullable": true }, "error": { "type": "object", "properties": { "code": { "type": "string" }, "message": { "type": "string" }, "details": { "nullable": true } }, "required": [ "code", "message" ] } }, "required": [ "id", "status" ] } } }, "required": [ "object", "data" ] } } } }, "413": { "description": "The request body exceeded 5 MB.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Redirects" ], "operationId": "batchRedirects" } }, "/redirects/{id}": { "patch": { "summary": "Update a redirect rule", "description": "Updates the specified redirect by setting the values of the parameters passed. Any parameters not provided will be left unchanged.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The redirect ID returned by create or list endpoints." }, "required": true, "description": "The redirect ID returned by create or list endpoints.", "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateRedirectBody" } } } }, "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Redirect" } } } }, "400": { "description": "The request was malformed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Redirect not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The new fromPath collides with another redirect.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Redirects" ], "operationId": "updateRedirect" }, "delete": { "summary": "Delete a redirect rule", "description": "Permanently deletes a redirect rule. It cannot be undone.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The redirect ID returned by create or list endpoints." }, "required": true, "description": "The redirect ID returned by create or list endpoints.", "name": "id", "in": "path" } ], "responses": { "204": { "description": "Successful response." }, "404": { "description": "Redirect not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Redirects" ], "operationId": "deleteRedirect" } }, "/sales-led-plans": { "get": { "summary": "List sales-led plans", "description": "List active (non-archived) contact-led pricing cards for the Board, ordered by `displayOrder`. Requires `plans.read`.", "responses": { "200": { "description": "A list of sales-led plans.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/sales-led-plans" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/AdminSalesLedPlan" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Sales-led plans" ], "operationId": "listSalesLedPlans" }, "post": { "summary": "Create a sales-led plan", "description": "Create a contact-led pricing card. Destination is normalized (email → mailto:, bare domain → https://). Max five featured bullets; max 50 active plans. Requires `plans.manage` and an `Idempotency-Key` header.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateSalesLedPlanBody" } } } }, "responses": { "201": { "description": "The created sales-led plan.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AdminSalesLedPlan" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Sales-led plans" ], "operationId": "createSalesLedPlan" } }, "/sales-led-plans/reorder": { "post": { "summary": "Reorder sales-led plans", "description": "Atomically set `displayOrder` for the complete active set. Rejects missing, foreign, archived, or duplicate IDs and duplicate orders. Requires `plans.manage` and an `Idempotency-Key` header.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReorderSalesLedPlansBody" } } } }, "responses": { "200": { "description": "The reordered list of active sales-led plans.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/sales-led-plans" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/AdminSalesLedPlan" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Sales-led plans" ], "operationId": "reorderSalesLedPlans" } }, "/sales-led-plans/{id}": { "get": { "summary": "Retrieve a sales-led plan", "description": "Retrieve one active sales-led plan. Foreign and archived IDs return opaque 404. Requires `plans.read`.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The sales-led plan ID returned by create or list endpoints." }, "required": true, "description": "The sales-led plan ID returned by create or list endpoints.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "The sales-led plan.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AdminSalesLedPlan" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Sales-led plans" ], "operationId": "getSalesLedPlan" }, "patch": { "summary": "Update a sales-led plan", "description": "Replace the editable fields of an active sales-led plan (matches the dashboard form). Requires `plans.manage` and an `Idempotency-Key` header.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The sales-led plan ID returned by create or list endpoints." }, "required": true, "description": "The sales-led plan ID returned by create or list endpoints.", "name": "id", "in": "path" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateSalesLedPlanBody" } } } }, "responses": { "200": { "description": "The updated sales-led plan.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AdminSalesLedPlan" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Sales-led plans" ], "operationId": "updateSalesLedPlan" } }, "/sales-led-plans/{id}/archive": { "post": { "summary": "Archive a sales-led plan", "description": "Irreversibly archive the plan (soft-delete). Sets `isArchived: true` and `isPublic: false`. Archived IDs become opaque 404. Requires `plans.manage` and an `Idempotency-Key` header.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The sales-led plan ID returned by create or list endpoints." }, "required": true, "description": "The sales-led plan ID returned by create or list endpoints.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "The archived sales-led plan.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AdminSalesLedPlan" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Sales-led plans" ], "operationId": "archiveSalesLedPlan" } }, "/sales-led-plans/{id}/hide": { "post": { "summary": "Hide a sales-led plan", "description": "Hide the plan from the public employer pricing page (`isPublic: false`) without archiving it. Requires `plans.manage` and an `Idempotency-Key` header.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The sales-led plan ID returned by create or list endpoints." }, "required": true, "description": "The sales-led plan ID returned by create or list endpoints.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "The hidden sales-led plan.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AdminSalesLedPlan" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Sales-led plans" ], "operationId": "hideSalesLedPlan" } }, "/sales-led-plans/{id}/publish": { "post": { "summary": "Publish a sales-led plan", "description": "Make the plan public on the employer pricing page (`isPublic: true`). Requires `plans.manage` and an `Idempotency-Key` header.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The sales-led plan ID returned by create or list endpoints." }, "required": true, "description": "The sales-led plan ID returned by create or list endpoints.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "The published sales-led plan.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AdminSalesLedPlan" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Sales-led plans" ], "operationId": "publishSalesLedPlan" } }, "/settings": { "get": { "summary": "Retrieve board settings", "description": "Retrieves the settings for your board.", "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Settings" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Settings" ], "operationId": "getSettings" }, "patch": { "summary": "Update board settings", "description": "Updates typed board settings by setting the values supplied. Omitted values remain unchanged; settings outside this allowlist use their dedicated product endpoint.", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PatchSettingsBody" } } } }, "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Settings" } } } }, "400": { "description": "The request was malformed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "description": "The account's plan tier does not permit this change. Common cases include disabling password protection on a plan that requires it, and removing Cavuno branding on a plan that does not allow it.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The supplied slug is already in use, or password protection cannot be enabled until a password is set via `POST /v1/settings/password-protection`.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Settings" ], "operationId": "updateSettings" } }, "/settings/adsense": { "get": { "summary": "Retrieve AdSense configuration", "description": "Retrieves the AdSense configuration for your board.", "responses": { "200": { "description": "Successful response." }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Settings" ], "operationId": "getAdsenseSettings" }, "put": { "summary": "Update AdSense configuration", "description": "Replaces the AdSense configuration for your board with the supplied values.", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SettingsAdsenseBody" } } } }, "responses": { "200": { "description": "Successful response." }, "400": { "description": "The supplied AdSense client ID is not in the required `ca-pub-XXXXXXXXXXXXXXXX` format.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Settings" ], "operationId": "updateAdsenseSettings" } }, "/settings/hero": { "delete": { "summary": "Delete the board hero image", "description": "Removes the hero image from your board.", "responses": { "204": { "description": "Successful response." }, "409": { "description": "No hero image is currently set.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Settings" ], "operationId": "deleteHeroImage" } }, "/settings/job-form": { "get": { "summary": "Retrieve the job form configuration", "description": "Retrieves the board's job form configuration: built-in field tuning plus any custom field definitions. Read this before writing custom-field values: each definition's `key`, `type`, and `options` tell you what to send in the `customFieldValues` object on `POST`/`PATCH /v1/jobs`. Returns an empty object when the board has not configured it.", "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/JobFormConfig" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Settings" ], "operationId": "getJobFormSettings" } }, "/settings/job-form/custom-fields": { "put": { "summary": "Replace custom job field definitions", "description": "Whole-array replace of the board's custom job field definitions (`jobFormConfig.customFields` only: other job-form keys are untouched). Array order is display order. Empty array removes all fields. Content validation rejects empty labels, duplicate keys, optionless selects, inverted number bounds, and cap breaches (400). Changing `type` on an existing key is rejected (422 `settings_custom_field_type_immutable`); delete the field and recreate it. Renaming a key is delete+add and orphans per-job values under the old key. Response shape matches `GET /v1/settings/job-form`.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/JobFormCustomFieldsBody" } } } }, "responses": { "200": { "description": "Updated job form configuration (same shape as GET /settings/job-form).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/JobFormConfig" } } } }, "400": { "description": "Content validation failed (duplicate keys, optionless select, etc.).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "description": "Attempted to change `type` on an existing custom field key.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Settings" ], "operationId": "updateJobFormCustomFields" } }, "/settings/password-protection": { "post": { "summary": "Enable password protection", "description": "Enables password protection for your board with the supplied password. The password must be at least eight characters.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SettingsPasswordProtectionBody" } } } }, "responses": { "200": { "description": "Successful response." }, "400": { "description": "The password is shorter than the 8-character minimum.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Settings" ], "operationId": "enablePasswordProtection" }, "delete": { "summary": "Disable password protection", "description": "Disables password protection on your board. Free-plan accounts cannot disable password protection and will receive a 403.", "responses": { "204": { "description": "Successful response." }, "403": { "description": "The account's plan tier does not permit a public board; password protection cannot be disabled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Password protection is not currently enabled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Settings" ], "operationId": "disablePasswordProtection" } }, "/subscribers": { "get": { "summary": "List subscribers", "description": "Returns the subscribers of the authenticated account. Alerts are not inlined here. Fetch them via `GET /v1/subscribers/{id}/alerts`. Requires `alerts.read`.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "Pagination cursor." }, "required": false, "description": "Pagination cursor.", "name": "cursor", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Page size (1–100, default 50)." }, "required": false, "description": "Page size (1–100, default 50).", "name": "limit", "in": "query" }, { "schema": { "type": "string", "minLength": 1, "description": "Case-insensitive substring match on the subscriber email." }, "required": false, "description": "Case-insensitive substring match on the subscriber email.", "name": "search", "in": "query" }, { "schema": { "type": "string", "enum": [ "confirmed", "unconfirmed", "unsubscribed", "waitlisted" ], "description": "Filter subscribers by lifecycle status." }, "required": false, "description": "Filter subscribers by lifecycle status.", "name": "status", "in": "query" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/subscribers" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Subscriber" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Subscribers" ], "operationId": "listSubscribers" } }, "/subscribers/count": { "get": { "summary": "Count confirmed subscribers", "description": "Returns the count of confirmed subscribers for the account. Cheap and cacheable. Requires `alerts.read`. Note: this counts every subscriber that has ever confirmed and is not decremented on unsubscribe, so it can exceed the size of `GET /v1/subscribers?status=confirmed` (which additionally excludes unsubscribed rows).", "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SubscriberCount" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Subscribers" ], "operationId": "countSubscribers" } }, "/subscribers/export": { "get": { "summary": "Export subscribers", "description": "Exports the account’s subscribers. `format=json` returns an inline list (max 10,000 rows). `format=csv` (default) returns `202` with an operation. Poll it, then download the CSV from `GET /v1/operations/{id}/download` once it succeeds. Requires `alerts.read`.", "parameters": [ { "schema": { "type": "string", "enum": [ "csv", "json" ], "default": "csv", "description": "Export format. `json` streams an inline list (capped at 10,000 rows); `csv` starts an async `subscribers.export` operation whose CSV is downloadable from `GET /v1/operations/{id}/download` once it succeeds." }, "required": false, "description": "Export format. `json` streams an inline list (capped at 10,000 rows); `csv` starts an async `subscribers.export` operation whose CSV is downloadable from `GET /v1/operations/{id}/download` once it succeeds.", "name": "format", "in": "query" } ], "responses": { "200": { "description": "Inline JSON export (`format=json`).", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/subscribers/export" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Subscriber" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "202": { "description": "A `subscribers.export` operation was started (`format=csv`). Poll the operation; once it succeeds, download the CSV from `GET /v1/operations/{id}/download`.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OperationResource" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Subscribers" ], "operationId": "exportSubscribers" } }, "/subscribers/import": { "post": { "summary": "Import subscribers", "description": "Bulk-imports subscribers from a CSV upload (`multipart/form-data`, field `file`; 10MB / 50,000-row max). `sendConfirmation` defaults to `true`. Returns `202` with a `subscribers.import` operation. Poll it; the terminal result is `{ totalRows, created, skippedDuplicates, failed, errors[] }`. Imported subscribers remain unconfirmed and do not receive active alerts until they complete opt-in. Requires `alerts.manage`.", "requestBody": { "required": true, "content": { "multipart/form-data": { "schema": { "type": "object", "properties": { "file": { "type": "string", "format": "binary", "description": "The CSV file (header row with an `email` column)." }, "sendConfirmation": { "type": "boolean", "default": true, "description": "Whether to send a double-opt-in confirmation email to imported unconfirmed subscribers." } }, "required": [ "file" ] } } } }, "responses": { "202": { "description": "A `subscribers.import` operation was started. Poll it for the terminal import summary.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OperationResource" } } } }, "400": { "description": "Unsupported file format (CSV only).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "413": { "description": "The import file exceeds the size limit.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Subscribers" ], "operationId": "importSubscribers" } }, "/subscribers/{id}": { "get": { "summary": "Retrieve a subscriber", "description": "Fetches a single subscriber with their alerts inline. Requires `alerts.read`.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The subscriber ID." }, "required": true, "description": "The subscriber ID.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SubscriberDetail" } } } }, "404": { "description": "Subscriber not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Subscribers" ], "operationId": "getSubscriber" } }, "/subscribers/{id}/alerts": { "get": { "summary": "List a subscriber’s alerts", "description": "Returns the alerts belonging to a specific subscriber. Requires `alerts.read`.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The subscriber ID." }, "required": true, "description": "The subscriber ID.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/subscribers/subscribers_k1000abc/alerts" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "allOf": [ { "$ref": "#/components/schemas/Alert" }, { "properties": { "id": { "type": "string", "description": "Unique identifier for the alert." }, "object": { "type": "string", "enum": [ "alert" ], "description": "String representing the object's type." }, "subscriberId": { "type": "string", "description": "Identifier of the subscriber that owns this alert." }, "filters": { "nullable": true, "description": "The job-filter criteria the alert matches against." }, "frequency": { "type": "string", "description": "Delivery cadence: `instant`, `daily`, or `weekly`." }, "isActive": { "type": "boolean", "description": "Whether the alert is currently active." }, "lastSentAt": { "type": "string", "nullable": true, "description": "ISO-8601 timestamp of the last dispatch, or `null`." }, "createdAt": { "type": "string", "description": "ISO-8601 timestamp of when the alert was created." } }, "required": [ "id", "object", "subscriberId", "frequency", "isActive", "lastSentAt", "createdAt" ] } ] } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "404": { "description": "Subscriber not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Subscribers" ], "operationId": "listSubscriberAlerts" } }, "/subscribers/{id}/resubscribe": { "post": { "summary": "Resubscribe a subscriber", "description": "Admin-initiated resubscribe: clears `unsubscribedAt` and reactivates the subscriber’s alerts after email confirmation. Requires `alerts.manage`.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The subscriber ID." }, "required": true, "description": "The subscriber ID.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SubscriberDetail" } } } }, "404": { "description": "Subscriber not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The subscriber is not currently unsubscribed or has not confirmed their email.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Subscribers" ], "operationId": "resubscribeSubscriber" } }, "/subscribers/{id}/unsubscribe": { "post": { "summary": "Unsubscribe a subscriber", "description": "Admin-initiated unsubscribe: sets `unsubscribedAt` and deactivates the subscriber’s alerts. Requires `alerts.manage`.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The subscriber ID." }, "required": true, "description": "The subscriber ID.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SubscriberDetail" } } } }, "404": { "description": "Subscriber not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "The subscriber is already unsubscribed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Subscribers" ], "operationId": "unsubscribeSubscriber" } }, "/taxonomies/categories": { "get": { "summary": "List categories", "description": "Returns a paginated list of your categories. Nesting is expressed by `parentId`; for the assembled hierarchy use `GET /v1/taxonomies/categories/tree`.", "parameters": [ { "schema": { "type": "string", "minLength": 1 }, "required": false, "name": "cursor", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 100 }, "required": false, "name": "limit", "in": "query" }, { "schema": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Full-text search over the taxonomy name (matches name tokens, not slug)." }, "required": false, "description": "Full-text search over the taxonomy name (matches name tokens, not slug).", "name": "search", "in": "query" }, { "schema": { "type": "string", "minLength": 1, "description": "Filter to a parent category id, or the literal \"null\" for top-level categories. When set, a page may be short or empty while hasMore is true: keep paging until hasMore is false." }, "required": false, "description": "Filter to a parent category id, or the literal \"null\" for top-level categories. When set, a page may be short or empty while hasMore is true: keep paging until hasMore is false.", "name": "parentId", "in": "query" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/taxonomies/categories" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Category" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Categories" ], "operationId": "listTaxonomiesCategories" }, "post": { "summary": "Create a category", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateCategoryBody" } } } }, "responses": { "201": { "description": "Created.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Category" } } } }, "409": { "description": "Slug taken.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Categories" ], "operationId": "createTaxonomiesCategory" } }, "/taxonomies/categories/tree": { "get": { "summary": "Retrieve the category tree", "description": "Returns top-level categories with their descendants nested under `children`. The same data as `GET /v1/taxonomies/categories`, assembled into a hierarchy for menus and pickers. Not paginated: capped at 1000 nodes, above which it returns 400. Page the flat list for larger taxonomies.", "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/taxonomies/categories/tree" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Category" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "400": { "description": "Tree too large.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Categories" ], "operationId": "getTaxonomiesCategoryTree" } }, "/taxonomies/categories/{id}": { "get": { "summary": "Retrieve a category", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The category's opaque object id (not the slug). Use list/create responses to obtain it." }, "required": true, "description": "The category's opaque object id (not the slug). Use list/create responses to obtain it.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Category" } } } }, "404": { "description": "Not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Categories" ], "operationId": "getTaxonomiesCategory" }, "patch": { "summary": "Update a category", "description": "Partial update. parentId cycles rejected with taxonomy_parent_cycle. Slug change dual-writes aliases and cascades job denorm.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The category's opaque object id (not the slug). Use list/create responses to obtain it." }, "required": true, "description": "The category's opaque object id (not the slug). Use list/create responses to obtain it.", "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateCategoryBody" } } } }, "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Category" } } } }, "400": { "description": "Parent cycle.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Slug taken.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Categories" ], "operationId": "updateTaxonomiesCategory" }, "delete": { "summary": "Delete a category", "description": "Deletes the category and its direct children only (1-level cascade). Grandchildren are not removed.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The category's opaque object id (not the slug). Use list/create responses to obtain it." }, "required": true, "description": "The category's opaque object id (not the slug). Use list/create responses to obtain it.", "name": "id", "in": "path" } ], "responses": { "204": { "description": "Deleted." }, "404": { "description": "Not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Categories" ], "operationId": "deleteTaxonomiesCategory" } }, "/taxonomies/categories/{id}/aliases": { "post": { "summary": "Add category aliases", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The category's opaque object id (not the slug). Use list/create responses to obtain it." }, "required": true, "description": "The category's opaque object id (not the slug). Use list/create responses to obtain it.", "name": "id", "in": "path" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AddCategoryAliasesBody" } } } }, "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Category" } } } }, "409": { "description": "Alias taken.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Categories" ], "operationId": "createTaxonomiesCategoryAlias" } }, "/taxonomies/categories/{id}/aliases/{alias}": { "delete": { "summary": "Remove a category alias", "parameters": [ { "schema": { "type": "string", "minLength": 1 }, "required": true, "name": "id", "in": "path" }, { "schema": { "type": "string", "minLength": 1 }, "required": true, "name": "alias", "in": "path" } ], "responses": { "204": { "description": "Removed." }, "404": { "description": "Not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Categories" ], "operationId": "deleteTaxonomiesCategoryAlias" } }, "/taxonomies/markets": { "get": { "summary": "List markets", "description": "List company-market taxonomy entries for the authenticated account.", "parameters": [ { "schema": { "type": "string", "minLength": 1 }, "required": false, "name": "cursor", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 100 }, "required": false, "name": "limit", "in": "query" }, { "schema": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Full-text search over the taxonomy name (matches name tokens, not slug)." }, "required": false, "description": "Full-text search over the taxonomy name (matches name tokens, not slug).", "name": "search", "in": "query" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/taxonomies/markets" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Market" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Markets" ], "operationId": "listTaxonomiesMarkets" }, "post": { "summary": "Create a market", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateMarketBody" } } } }, "responses": { "201": { "description": "Created.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Market" } } } }, "409": { "description": "Slug taken.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Markets" ], "operationId": "createTaxonomiesMarket" } }, "/taxonomies/markets/{id}": { "get": { "summary": "Retrieve a market", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The market's opaque object id (not the slug). Use list/create responses to obtain it." }, "required": true, "description": "The market's opaque object id (not the slug). Use list/create responses to obtain it.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Market" } } } }, "404": { "description": "Not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Markets" ], "operationId": "getTaxonomiesMarket" }, "patch": { "summary": "Update a market", "description": "Partial update. Changing slug auto-adds the previous slug to aliasSlugs and taxonomyAliases. Does not cascade to companies.markets arrays (rely on alias resolution).", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The market's opaque object id (not the slug). Use list/create responses to obtain it." }, "required": true, "description": "The market's opaque object id (not the slug). Use list/create responses to obtain it.", "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateMarketBody" } } } }, "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Market" } } } }, "404": { "description": "Not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Slug taken.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Markets" ], "operationId": "updateTaxonomiesMarket" }, "delete": { "summary": "Delete a market", "description": "Deletes the market taxonomy row. Companies may retain stale market slugs (by design).", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The market's opaque object id (not the slug). Use list/create responses to obtain it." }, "required": true, "description": "The market's opaque object id (not the slug). Use list/create responses to obtain it.", "name": "id", "in": "path" } ], "responses": { "204": { "description": "Deleted." }, "404": { "description": "Not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Markets" ], "operationId": "deleteTaxonomiesMarket" } }, "/taxonomies/markets/{id}/aliases": { "post": { "summary": "Add market aliases", "description": "Dual-writes aliasSlugs and taxonomyAliases. Max 20 aliases per request.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The market's opaque object id (not the slug). Use list/create responses to obtain it." }, "required": true, "description": "The market's opaque object id (not the slug). Use list/create responses to obtain it.", "name": "id", "in": "path" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AddMarketAliasesBody" } } } }, "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Market" } } } }, "409": { "description": "Alias taken.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Markets" ], "operationId": "createTaxonomiesMarketAlias" } }, "/taxonomies/markets/{id}/aliases/{alias}": { "delete": { "summary": "Remove a market alias", "parameters": [ { "schema": { "type": "string", "minLength": 1 }, "required": true, "name": "id", "in": "path" }, { "schema": { "type": "string", "minLength": 1 }, "required": true, "name": "alias", "in": "path" } ], "responses": { "204": { "description": "Removed." }, "404": { "description": "Market or alias not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Markets" ], "operationId": "deleteTaxonomiesMarketAlias" } }, "/taxonomies/remote-permits": { "get": { "summary": "List remote permits", "description": "Returns the canonical `{type, value, label}` set accepted by the `remotePermits` field on `POST /v1/jobs` and `PATCH /v1/jobs/:id`. Public: no authentication required. Cached for 6h.", "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/taxonomies/remote-permits" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/RemotePermitTaxonomyEntry" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Remote taxonomies" ], "operationId": "listTaxonomiesRemotePermits" } }, "/taxonomies/remote-timezones": { "get": { "summary": "List remote timezones", "description": "Returns the canonical `{type, value, label}` set accepted by the `remoteTimezones` field on `POST /v1/jobs` and `PATCH /v1/jobs/:id`. Public: no authentication required. Cached for 6h.", "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/taxonomies/remote-timezones" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/RemoteTimezoneTaxonomyEntry" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Remote taxonomies" ], "operationId": "listTaxonomiesRemoteTimezones" } }, "/taxonomies/skills": { "get": { "summary": "List skills", "description": "List taxonomy skills for the authenticated account.", "parameters": [ { "schema": { "type": "string", "minLength": 1 }, "required": false, "name": "cursor", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 100 }, "required": false, "name": "limit", "in": "query" }, { "schema": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Full-text search over the taxonomy name (matches name tokens, not slug)." }, "required": false, "description": "Full-text search over the taxonomy name (matches name tokens, not slug).", "name": "search", "in": "query" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/taxonomies/skills" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Skill" } } }, "required": [ "object", "url", "hasMore", "nextCursor", "data" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Skills" ], "operationId": "listTaxonomiesSkills" }, "post": { "summary": "Create a skill", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateSkillBody" } } } }, "responses": { "201": { "description": "Created.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Skill" } } } }, "409": { "description": "Slug taken.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Skills" ], "operationId": "createTaxonomiesSkill" } }, "/taxonomies/skills/{id}": { "get": { "summary": "Retrieve a skill", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The skill's opaque object id (not the slug). Use list/create responses to obtain it." }, "required": true, "description": "The skill's opaque object id (not the slug). Use list/create responses to obtain it.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Skill" } } } }, "404": { "description": "Not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Skills" ], "operationId": "getTaxonomiesSkill" }, "patch": { "summary": "Update a skill", "description": "Partial update. Changing slug auto-adds the previous slug to aliasSlugs and taxonomyAliases and cascades denormalized job data.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The skill's opaque object id (not the slug). Use list/create responses to obtain it." }, "required": true, "description": "The skill's opaque object id (not the slug). Use list/create responses to obtain it.", "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateSkillBody" } } } }, "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Skill" } } } }, "404": { "description": "Not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Slug taken.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Skills" ], "operationId": "updateTaxonomiesSkill" }, "delete": { "summary": "Delete a skill", "description": "Deletes the skill. Jobs may retain stale skill slugs (by design).", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The skill's opaque object id (not the slug). Use list/create responses to obtain it." }, "required": true, "description": "The skill's opaque object id (not the slug). Use list/create responses to obtain it.", "name": "id", "in": "path" } ], "responses": { "204": { "description": "Deleted." }, "404": { "description": "Not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Skills" ], "operationId": "deleteTaxonomiesSkill" } }, "/taxonomies/skills/{id}/aliases": { "post": { "summary": "Add skill aliases", "description": "Dual-writes aliasSlugs and taxonomyAliases. Max 20 aliases per request.", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The skill's opaque object id (not the slug). Use list/create responses to obtain it." }, "required": true, "description": "The skill's opaque object id (not the slug). Use list/create responses to obtain it.", "name": "id", "in": "path" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AddSkillAliasesBody" } } } }, "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Skill" } } } }, "409": { "description": "Alias taken.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Skills" ], "operationId": "createTaxonomiesSkillAlias" } }, "/taxonomies/skills/{id}/aliases/{alias}": { "delete": { "summary": "Remove a skill alias", "parameters": [ { "schema": { "type": "string", "minLength": 1 }, "required": true, "name": "id", "in": "path" }, { "schema": { "type": "string", "minLength": 1 }, "required": true, "name": "alias", "in": "path" } ], "responses": { "204": { "description": "Removed." }, "404": { "description": "Skill or alias not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Skills" ], "operationId": "deleteTaxonomiesSkillAlias" } }, "/transactions": { "get": { "summary": "List transactions", "description": "List revenue ledger rows for the tenant's board. Cursor-paginated. Filters: status, kind, and search (full-text, relevance-ordered). Past-due is not a stored status. Derive it client-side from invoiceDueAt.", "parameters": [ { "schema": { "type": "string", "minLength": 1 }, "required": false, "name": "cursor", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 100 }, "required": false, "name": "limit", "in": "query" }, { "schema": { "type": "string", "enum": [ "paid", "open", "void", "uncollectible" ] }, "required": false, "name": "status", "in": "query" }, { "schema": { "type": "string", "enum": [ "card_post", "invoice", "subscription" ] }, "required": false, "name": "kind", "in": "query" }, { "schema": { "type": "string", "minLength": 1 }, "required": false, "name": "search", "in": "query" } ], "responses": { "200": { "description": "Paginated transactions with sortedBy.", "content": { "application/json": { "schema": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "list" ] }, "url": { "type": "string", "example": "/v1/transactions" }, "hasMore": { "type": "boolean" }, "nextCursor": { "type": "string", "nullable": true }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Transaction" } }, "sortedBy": { "type": "string", "enum": [ "date", "relevance" ], "description": "Sort mode: \"relevance\" when `search` is present, otherwise \"date\" (date-desc)." } }, "required": [ "object", "url", "hasMore", "nextCursor", "data", "sortedBy" ] } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Transactions" ], "operationId": "listTransactions" } }, "/transactions/{id}": { "get": { "summary": "Get a transaction", "description": "Fetch one transaction by id. Cross-tenant ids return 404 (indistinguishable from missing).", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "The transaction ID." }, "required": true, "description": "The transaction ID.", "name": "id", "in": "path" } ], "responses": { "200": { "description": "The transaction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Transaction" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Transactions" ], "operationId": "getTransaction" } }, "/usage": { "get": { "summary": "Retrieve account usage", "description": "Retrieves actionable product capacity for your Board: used, limit, and remaining for active jobs, confirmed subscribers, and team seats. Unlimited capacities use null limit and remaining. Plan details live on GET /billing/subscription.", "responses": { "200": { "description": "Successful response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Usage" } } } }, "default": { "description": "An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "x-audience": "operator", "tags": [ "Usage" ], "operationId": "getUsage" } } }, "tags": [ { "name": "Jobs", "description": "Create, list, update, and publish jobs." }, { "name": "Usage", "description": "Your account's actionable product capacity (used, limit, remaining)." }, { "name": "Companies", "description": "Create, list, update, and delete companies attached to jobs." }, { "name": "Media", "description": "Upload and manage logos and other binary assets." }, { "name": "Settings", "description": "Read and update your board settings." }, { "name": "Operations", "description": "Track long-running asynchronous operations." }, { "name": "Domains", "description": "Add, list, remove, and verify custom domains." }, { "name": "Redirects", "description": "Create, list, update, and delete board redirect rules." }, { "name": "Skills", "description": "Create, list, update, and delete job skills, and manage their aliases." }, { "name": "Categories", "description": "Create, list, update, and delete job categories, and manage their aliases." }, { "name": "Markets", "description": "Create, list, update, and delete job markets, and manage their aliases." }, { "name": "Remote taxonomies", "description": "Reference values accepted by the remote-permit and remote-timezone job fields." }, { "name": "Operator", "description": "Current operator identity: Board binding, actor type, live role, and effective permissions/scopes." }, { "name": "Members", "description": "List, update, suspend, and remove team members, and read roles and permissions." }, { "name": "Invitations", "description": "Create, list, renew, and accept account invitations." }, { "name": "Subscribers", "description": "Job-alert subscribers: list, export, un/resubscribe, and import." }, { "name": "Candidates", "description": "Candidates registered on your board: list, view, delete." }, { "name": "Employers", "description": "Employers on your board: list, view, company claims, and memberships." }, { "name": "Billing", "description": "Your account's platform subscription, entitlements, checkout, upgrade, and Stripe Connect status." }, { "name": "Plans", "description": "Job-posting plans sold on your board: create, publish, price, and features." }, { "name": "Sales-led plans", "description": "Contact-led employer pricing cards: create, reorder, publish, hide, and archive." }, { "name": "Coupons", "description": "Coupons and promotion codes on your connected Stripe account." }, { "name": "Transactions", "description": "Unified billing ledger: job-posting orders and employer-subscription transactions." }, { "name": "Employer subscriptions", "description": "Employer job-posting subscriptions on your board." }, { "name": "Paywall", "description": "Candidate-access paywall configuration, offers, and subscription state." }, { "name": "Blog posts", "description": "Create, list, publish, and delete blog posts, and run batched post operations." }, { "name": "Blog authors", "description": "Create, list, update, and delete blog authors." }, { "name": "Blog tags", "description": "Create, list, update, and delete blog tags." }, { "name": "Imports", "description": "Bulk job imports: upload, map fields, confirm, and track progress." }, { "name": "Backfill", "description": "Named Backfill rules, company sources, and aggregate progress for collecting jobs into a Board." }, { "name": "Analytics", "description": "Typed Board homepage analytics: overview metrics and traffic tables." }, { "name": "Integrations", "description": "Search-indexing and analytics-reporting integrations." } ], "components": { "securitySchemes": { "bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "cavuno_live__", "description": "Use your secret API key to authenticate. Pass it as a Bearer token in the `Authorization` header. You can view and manage your API keys in the Cavuno dashboard." } }, "schemas": { "AnalyticsOverview": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "analytics_overview" ] }, "range": { "$ref": "#/components/schemas/AnalyticsDateRange" }, "comparisonRange": { "$ref": "#/components/schemas/AnalyticsDateRange" }, "currentVisitors": { "type": "integer", "minimum": 0, "description": "Realtime visitors on the board right now." }, "metrics": { "type": "array", "items": { "$ref": "#/components/schemas/AnalyticsMetric" } } }, "required": [ "object", "range", "comparisonRange", "currentVisitors", "metrics" ] }, "Error": { "type": "object", "properties": { "error": { "type": "object", "properties": { "code": { "type": "string", "description": "Machine-readable error code, such as `validation_bad_request` or `jobs_not_found`." }, "message": { "type": "string", "description": "Human-readable explanation." }, "requestId": { "type": "string", "description": "Unique id for this request. Include it when contacting support." }, "details": { "nullable": true, "description": "Structured context for some errors, such as per-field validation issues." } }, "required": [ "code", "message", "requestId" ] } }, "required": [ "error" ], "description": "The error envelope returned by every non-2xx response." }, "AnalyticsTraffic": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "analytics_traffic" ] }, "range": { "$ref": "#/components/schemas/AnalyticsTrafficDateRange" }, "pages": { "type": "array", "items": { "$ref": "#/components/schemas/AnalyticsTrafficPage" } }, "sources": { "type": "array", "items": { "$ref": "#/components/schemas/AnalyticsTrafficSource" } }, "locations": { "type": "array", "items": { "$ref": "#/components/schemas/AnalyticsTrafficLocation" } }, "devices": { "type": "array", "items": { "$ref": "#/components/schemas/AnalyticsTrafficDevice" } } }, "required": [ "object", "range", "pages", "sources", "locations", "devices" ] }, "BackfillCompany": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "backfill_company" ] }, "companyId": { "type": "string" }, "name": { "type": "string" }, "website": { "type": "string", "nullable": true }, "state": { "type": "string", "enum": [ "backfilling", "available", "needs_match", "not_backfilling" ] }, "candidates": { "type": "array", "items": { "$ref": "#/components/schemas/BackfillMatchCandidate" } } }, "required": [ "object", "companyId", "name", "website", "state" ] }, "BulkBackfillCompaniesBody": { "type": "object", "properties": { "companyIds": { "type": "array", "items": { "type": "string", "minLength": 1 }, "minItems": 1, "maxItems": 100, "description": "Ordered Cavuno company IDs (max 100). Partial success is returned per item." } }, "required": [ "companyIds" ], "additionalProperties": false }, "BackfillBulkResult": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "backfill_bulk_result" ] }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/BackfillBulkItemResult" } } }, "required": [ "object", "data" ] }, "MatchBackfillCompanyBody": { "type": "object", "properties": { "candidateIndex": { "type": "integer", "minimum": 0, "description": "Zero-based index into the short-lived candidates array from list (needs_match). Re-validated server-side." }, "start": { "type": "boolean", "description": "When true, start backfill after linking the match; when false, only record the match (available)." } }, "required": [ "candidateIndex", "start" ], "additionalProperties": false }, "BackfillProgress": { "type": "object", "nullable": true, "properties": { "object": { "type": "string", "enum": [ "backfill_progress" ] }, "status": { "type": "string", "enum": [ "pending", "syncing", "enqueuing", "enhancing", "succeeded", "failed" ] }, "jobsMatched": { "type": "integer", "minimum": 0 }, "jobsToEnhance": { "type": "integer", "minimum": 0 }, "jobsEnhanced": { "type": "integer", "minimum": 0 }, "jobsFailed": { "type": "integer", "minimum": 0 } }, "required": [ "object", "status", "jobsMatched", "jobsToEnhance", "jobsEnhanced", "jobsFailed" ] }, "BackfillRule": { "type": "object", "properties": { "id": { "type": "string", "description": "Stable Cavuno-owned resource ID." }, "object": { "type": "string", "enum": [ "backfill_rule" ] }, "name": { "type": "string" }, "matchMode": { "type": "string", "enum": [ "any", "all" ] }, "rules": { "type": "array", "items": { "type": "object", "properties": { "match": { "type": "string", "enum": [ "any", "all" ] }, "conditions": { "type": "array", "items": { "type": "object", "properties": { "field": { "type": "string", "enum": [ "title", "description" ] }, "operator": { "type": "string", "enum": [ "contains_any", "contains_all", "is_not" ] }, "terms": { "type": "array", "items": { "type": "string" } } }, "required": [ "field", "operator", "terms" ] } } }, "required": [ "match", "conditions" ] } }, "filters": { "type": "object", "properties": { "countries": { "type": "array", "items": { "type": "string" } }, "subdivisions": { "type": "array", "items": { "type": "string" } }, "seniorities": { "type": "array", "items": { "type": "string" } }, "employmentTypes": { "type": "array", "items": { "type": "string" } }, "workplaceTypes": { "type": "array", "items": { "type": "string" } } } }, "createdAt": { "type": "string", "nullable": true }, "updatedAt": { "type": "string", "nullable": true } }, "required": [ "id", "object", "name", "matchMode", "rules", "filters", "createdAt", "updatedAt" ] }, "CreateBackfillRuleBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 2000 }, "matchMode": { "type": "string", "enum": [ "any", "all" ] }, "rules": { "type": "array", "items": { "type": "object", "properties": { "match": { "type": "string", "enum": [ "any", "all" ] }, "conditions": { "type": "array", "items": { "type": "object", "properties": { "field": { "type": "string", "enum": [ "title", "description" ] }, "operator": { "type": "string", "enum": [ "contains_any", "contains_all", "is_not" ] }, "terms": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 200 }, "minItems": 1, "maxItems": 20 } }, "required": [ "field", "operator", "terms" ], "additionalProperties": false }, "minItems": 1 } }, "required": [ "match", "conditions" ], "additionalProperties": false }, "minItems": 1 }, "filters": { "type": "object", "properties": { "countries": { "type": "array", "items": { "type": "string" } }, "subdivisions": { "type": "array", "items": { "type": "string" } }, "seniorities": { "type": "array", "items": { "type": "string", "enum": [ "entry_level", "associate", "mid_level", "senior", "director", "executive" ] } }, "employmentTypes": { "type": "array", "items": { "type": "string", "enum": [ "full_time", "part_time", "contract", "internship", "temporary", "volunteer", "other" ] } }, "workplaceTypes": { "type": "array", "items": { "type": "string", "enum": [ "remote", "hybrid", "onsite" ] } } }, "additionalProperties": false } }, "required": [ "name", "rules" ], "additionalProperties": false }, "UpdateBackfillRuleBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 2000 }, "matchMode": { "type": "string", "enum": [ "any", "all" ] }, "rules": { "type": "array", "items": { "type": "object", "properties": { "match": { "type": "string", "enum": [ "any", "all" ] }, "conditions": { "type": "array", "items": { "type": "object", "properties": { "field": { "type": "string", "enum": [ "title", "description" ] }, "operator": { "type": "string", "enum": [ "contains_any", "contains_all", "is_not" ] }, "terms": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 200 }, "minItems": 1, "maxItems": 20 } }, "required": [ "field", "operator", "terms" ], "additionalProperties": false }, "minItems": 1 } }, "required": [ "match", "conditions" ], "additionalProperties": false }, "minItems": 1 }, "filters": { "type": "object", "properties": { "countries": { "type": "array", "items": { "type": "string" } }, "subdivisions": { "type": "array", "items": { "type": "string" } }, "seniorities": { "type": "array", "items": { "type": "string", "enum": [ "entry_level", "associate", "mid_level", "senior", "director", "executive" ] } }, "employmentTypes": { "type": "array", "items": { "type": "string", "enum": [ "full_time", "part_time", "contract", "internship", "temporary", "volunteer", "other" ] } }, "workplaceTypes": { "type": "array", "items": { "type": "string", "enum": [ "remote", "hybrid", "onsite" ] } } }, "additionalProperties": false } }, "additionalProperties": false }, "BillingCheckoutBody": { "type": "object", "properties": { "planKey": { "type": "string", "enum": [ "starter", "basic", "grow", "advanced", "enterprise" ], "description": "Self-serve plan key. enterprise is not self-serve and returns plan_not_self_serve." }, "interval": { "type": "string", "enum": [ "monthly", "annual" ], "description": "Billing interval. Defaults to monthly when omitted." } }, "required": [ "planKey" ] }, "BillingCheckout": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "billing_checkout" ] }, "funding": { "$ref": "#/components/schemas/BillingHostedCheckoutFunding" }, "url": { "type": "string", "format": "uri", "description": "Short-lived hosted checkout URL." }, "planKey": { "type": "string", "enum": [ "starter", "basic", "grow", "advanced", "enterprise" ], "description": "Self-serve plan key. enterprise is not self-serve and returns plan_not_self_serve." }, "interval": { "type": "string", "enum": [ "monthly", "annual" ] } }, "required": [ "object", "funding", "url", "planKey", "interval" ] }, "BillingConnect": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "billing_connect" ] }, "connected": { "type": "boolean" }, "acceptingPayments": { "type": "boolean" }, "payoutsEnabled": { "type": "boolean" }, "detailsSubmitted": { "type": "boolean" }, "actionRequired": { "type": "boolean" } }, "required": [ "object", "connected", "acceptingPayments", "payoutsEnabled", "detailsSubmitted", "actionRequired" ] }, "BillingSubscription": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "billing_subscription" ] }, "active": { "type": "boolean" }, "status": { "type": "string", "nullable": true }, "planKey": { "type": "string", "nullable": true }, "currentPeriodEnd": { "type": "number", "nullable": true, "description": "Subscription period end as a millisecond epoch." }, "cancelAtPeriodEnd": { "type": "boolean" }, "capabilities": { "type": "object", "properties": { "activeJobsLimit": { "type": "number", "nullable": true }, "subscriberLimit": { "type": "number", "nullable": true }, "teamSeatLimit": { "type": "number", "nullable": true }, "canBePublic": { "type": "boolean" }, "canRemoveBranding": { "type": "boolean" }, "apiAccess": { "type": "boolean" } }, "required": [ "activeJobsLimit", "subscriberLimit", "teamSeatLimit", "canBePublic", "canRemoveBranding", "apiAccess" ] } }, "required": [ "object", "active", "status", "planKey", "currentPeriodEnd", "cancelAtPeriodEnd", "capabilities" ] }, "BillingUpgradeBody": { "type": "object", "properties": { "planKey": { "type": "string", "enum": [ "starter", "basic", "grow", "advanced", "enterprise" ], "description": "Self-serve plan key. enterprise is not self-serve and returns plan_not_self_serve." }, "interval": { "type": "string", "enum": [ "monthly", "annual" ], "description": "Billing interval. Defaults to monthly when omitted." } }, "required": [ "planKey" ] }, "BillingUpgrade": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "billing_upgrade" ] }, "funding": { "$ref": "#/components/schemas/BillingHostedCheckoutFunding" }, "status": { "type": "string", "enum": [ "human_action_required" ] }, "url": { "type": "string", "format": "uri" }, "planKey": { "type": "string", "enum": [ "starter", "basic", "grow", "advanced", "enterprise" ], "description": "Self-serve plan key. enterprise is not self-serve and returns plan_not_self_serve." } }, "required": [ "object", "funding", "status", "url", "planKey" ] }, "BlogAuthor": { "type": "object", "properties": { "id": { "type": "string", "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}`)." }, "object": { "type": "string", "enum": [ "blog_author" ], "description": "String representing the object's type. Objects of the same type share the same value." }, "name": { "type": "string", "description": "Display name of the author." }, "slug": { "type": "string", "description": "URL-friendly slug for the author." }, "bio": { "type": "string", "nullable": true, "description": "Short biography, or `null` if not set." }, "email": { "type": "string", "nullable": true, "description": "The author's email address, or `null` if not set." }, "status": { "type": "string", "nullable": true, "description": "Author visibility status, or `null` if not set." }, "avatarUrl": { "type": "string", "nullable": true, "description": "URL of the author avatar, or `null` if no avatar is set." }, "websiteUrl": { "type": "string", "nullable": true, "description": "The author's website URL, or `null` if not set." }, "twitterUrl": { "type": "string", "nullable": true, "description": "The author's X (Twitter) URL, or `null` if not set." }, "linkedinUrl": { "type": "string", "nullable": true, "description": "The author's LinkedIn URL, or `null` if not set." }, "githubUrl": { "type": "string", "nullable": true, "description": "The author's GitHub URL, or `null` if not set." }, "metaTitle": { "type": "string", "nullable": true, "description": "SEO meta title, or `null` if not set." }, "metaDescription": { "type": "string", "nullable": true, "description": "SEO meta description, or `null` if not set." }, "createdAt": { "type": "string", "description": "Time at which the author was created. ISO 8601 datetime." }, "updatedAt": { "type": "string", "nullable": true, "description": "Time at which the author was last updated, or `null` if it has never been updated. ISO 8601 datetime." } }, "required": [ "id", "object", "name", "slug", "bio", "email", "status", "avatarUrl", "websiteUrl", "twitterUrl", "linkedinUrl", "githubUrl", "metaTitle", "metaDescription", "createdAt", "updatedAt" ] }, "CreateAuthorBody": { "type": "object", "properties": { "slug": { "type": "string", "minLength": 1, "maxLength": 120, "pattern": "^[a-z0-9-]+$", "description": "URL-friendly slug for the author. Auto-generated from `name` when omitted." }, "bio": { "type": "string", "maxLength": 4000, "description": "Short biography for the author. Sanitized HTML." }, "email": { "type": "string", "maxLength": 320, "format": "email", "description": "The author's email address." }, "status": { "type": "string", "enum": [ "active", "inactive" ], "description": "Author visibility status. One of `active` or `inactive`." }, "avatarMediaId": { "type": "string", "nullable": true, "description": "Cavuno media ID of an uploaded avatar image. Pass `null` to clear it." }, "websiteUrl": { "type": "string", "maxLength": 500, "description": "The author's personal website URL. Normalized to a canonical URL when stored." }, "twitterUrl": { "type": "string", "maxLength": 500, "description": "The author's X (Twitter) profile URL. Stored as the canonical `https://x.com/` URL." }, "linkedinUrl": { "type": "string", "maxLength": 500, "description": "The author's LinkedIn profile URL." }, "githubUrl": { "type": "string", "maxLength": 500, "description": "The author's GitHub profile URL." }, "metaTitle": { "type": "string", "maxLength": 150, "description": "SEO meta title for the author page." }, "metaDescription": { "type": "string", "maxLength": 320, "description": "SEO meta description for the author page." }, "name": { "type": "string", "minLength": 1, "maxLength": 200, "description": "The author's display name." } }, "required": [ "name" ], "additionalProperties": false }, "ExportRow": { "type": "object", "properties": { "id": { "type": "string", "description": "Stable identifier for the exported row." } }, "required": [ "id" ], "additionalProperties": { "nullable": true }, "description": "A single export row. Fields mirror the entity’s CSV columns (camelCase); array fields are JSON arrays and timestamps are epoch-millisecond UTC numbers." }, "OperationResource": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique identifier for the object." }, "object": { "type": "string", "enum": [ "operation" ], "description": "String representing the object's type. Objects of the same type share the same value." }, "kind": { "type": "string", "enum": [ "domains.verify", "imports.parse", "imports.confirm", "subscribers.export", "subscribers.import", "exports.generate", "candidates.remove", "employers.remove" ], "description": "Operation kind, identifying which workflow the operation runs." }, "state": { "type": "string", "enum": [ "pending", "running", "succeeded", "failed", "cancelled" ], "description": "Current state of the operation." }, "progress": { "$ref": "#/components/schemas/OperationProgress" }, "error": { "$ref": "#/components/schemas/OperationErrorEnvelope" }, "createdAt": { "type": "string", "description": "Time at which the operation was created. ISO 8601 datetime." }, "updatedAt": { "type": "string", "description": "Time at which the operation was last updated. ISO 8601 datetime." }, "completedAt": { "type": "string", "nullable": true, "description": "Time at which the operation reached a terminal state, or `null` if it has not yet completed. ISO 8601 datetime." }, "cancelRequested": { "type": "boolean", "description": "Whether cancellation of the operation has been requested." }, "resource": { "type": "object", "nullable": true, "properties": { "object": { "type": "string", "enum": [ "company", "domain", "import", "employer", "candidate" ] }, "id": { "type": "string" } }, "required": [ "object", "id" ], "description": "Stable product resource affected by the operation, or `null` when no public resource applies." } }, "required": [ "id", "object", "kind", "state", "progress", "error", "createdAt", "updatedAt", "completedAt", "cancelRequested", "resource" ] }, "UpdateAuthorBody": { "type": "object", "properties": { "slug": { "type": "string", "minLength": 1, "maxLength": 120, "pattern": "^[a-z0-9-]+$", "description": "URL-friendly slug for the author. Auto-generated from `name` when omitted." }, "bio": { "type": "string", "maxLength": 4000, "description": "Short biography for the author. Sanitized HTML." }, "email": { "type": "string", "maxLength": 320, "format": "email", "description": "The author's email address." }, "status": { "type": "string", "enum": [ "active", "inactive" ], "description": "Author visibility status. One of `active` or `inactive`." }, "avatarMediaId": { "type": "string", "nullable": true, "description": "Cavuno media ID of an uploaded avatar image. Pass `null` to clear it." }, "websiteUrl": { "type": "string", "maxLength": 500, "description": "The author's personal website URL. Normalized to a canonical URL when stored." }, "twitterUrl": { "type": "string", "maxLength": 500, "description": "The author's X (Twitter) profile URL. Stored as the canonical `https://x.com/` URL." }, "linkedinUrl": { "type": "string", "maxLength": 500, "description": "The author's LinkedIn profile URL." }, "githubUrl": { "type": "string", "maxLength": 500, "description": "The author's GitHub profile URL." }, "metaTitle": { "type": "string", "maxLength": 150, "description": "SEO meta title for the author page." }, "metaDescription": { "type": "string", "maxLength": 320, "description": "SEO meta description for the author page." }, "name": { "type": "string", "minLength": 1, "maxLength": 200, "description": "The author's display name." } }, "additionalProperties": false }, "BlogPostSummary": { "type": "object", "properties": { "id": { "type": "string", "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}`)." }, "object": { "type": "string", "enum": [ "blog_post" ] }, "title": { "type": "string" }, "slug": { "type": "string" }, "status": { "type": "string" }, "visibility": { "type": "string" }, "type": { "type": "string" }, "featured": { "type": "boolean" }, "authorIds": { "type": "array", "items": { "type": "string" } }, "tagIds": { "type": "array", "items": { "type": "string" } }, "coverUrl": { "type": "string", "nullable": true }, "ogImageUrl": { "type": "string", "nullable": true }, "featureImageAlt": { "type": "string", "nullable": true }, "featureImageCaption": { "type": "string", "nullable": true }, "customExcerpt": { "type": "string", "nullable": true }, "readingTimeMin": { "type": "number", "nullable": true }, "seoTitle": { "type": "string", "nullable": true }, "seoDescription": { "type": "string", "nullable": true }, "canonicalUrl": { "type": "string", "nullable": true }, "publishedAt": { "type": "string", "nullable": true }, "createdAt": { "type": "string" }, "updatedAt": { "type": "string", "nullable": true } }, "required": [ "id", "object", "title", "slug", "status", "visibility", "type", "featured", "authorIds", "tagIds", "coverUrl", "ogImageUrl", "featureImageAlt", "featureImageCaption", "customExcerpt", "readingTimeMin", "seoTitle", "seoDescription", "canonicalUrl", "publishedAt", "createdAt", "updatedAt" ] }, "CreateBlogPostBody": { "type": "object", "properties": { "slug": { "type": "string", "minLength": 1, "maxLength": 120, "pattern": "^[a-z0-9-]+$" }, "html": { "type": "string", "maxLength": 1048576 }, "customExcerpt": { "type": "string", "maxLength": 500 }, "readingTimeMin": { "type": "integer", "minimum": 0, "maximum": 1000 }, "featured": { "type": "boolean" }, "authorIds": { "type": "array", "items": { "type": "string", "minLength": 1 }, "maxItems": 10 }, "tagIds": { "type": "array", "items": { "type": "string", "minLength": 1 }, "maxItems": 20 }, "coverMediaId": { "type": "string", "nullable": true, "minLength": 1 }, "ogImageMediaId": { "type": "string", "nullable": true, "minLength": 1 }, "featureImageAlt": { "type": "string", "maxLength": 200 }, "featureImageCaption": { "type": "string", "maxLength": 500 }, "seoTitle": { "type": "string", "maxLength": 150 }, "seoDescription": { "type": "string", "maxLength": 320 }, "canonicalUrl": { "type": "string", "maxLength": 500, "format": "uri" }, "publishedAt": { "type": "string", "format": "date-time" }, "title": { "type": "string", "minLength": 1, "maxLength": 200 }, "status": { "type": "string", "enum": [ "draft", "scheduled", "published" ] } }, "required": [ "title" ], "additionalProperties": false }, "BlogPost": { "allOf": [ { "$ref": "#/components/schemas/BlogPostSummary" }, { "type": "object", "properties": { "html": { "type": "string", "nullable": true } }, "required": [ "html" ] } ] }, "BlogPostsBatchRequest": { "type": "object", "properties": { "operations": { "type": "array", "items": { "oneOf": [ { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "method": { "type": "string", "enum": [ "POST" ] }, "body": { "nullable": true }, "action": { "type": "string" }, "resourceId": { "type": "string" } }, "required": [ "id", "method" ] }, { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "method": { "type": "string", "enum": [ "PATCH" ] }, "body": { "nullable": true }, "resourceId": { "type": "string", "minLength": 1 } }, "required": [ "id", "method", "resourceId" ] }, { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "method": { "type": "string", "enum": [ "DELETE" ] }, "resourceId": { "type": "string", "minLength": 1 } }, "required": [ "id", "method", "resourceId" ] } ] }, "minItems": 1, "maxItems": 50, "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." } }, "required": [ "operations" ], "additionalProperties": false }, "SearchBlogPostsBody": { "type": "object", "properties": { "query": { "type": "string", "maxLength": 200 }, "status": { "type": "string", "enum": [ "draft", "scheduled", "published" ] }, "cursor": { "type": "string", "nullable": true, "minLength": 1 }, "limit": { "type": "integer", "minimum": 1, "maximum": 100 } }, "additionalProperties": false }, "UpdateBlogPostBody": { "type": "object", "properties": { "slug": { "type": "string", "minLength": 1, "maxLength": 120, "pattern": "^[a-z0-9-]+$" }, "html": { "type": "string", "maxLength": 1048576 }, "customExcerpt": { "type": "string", "maxLength": 500 }, "readingTimeMin": { "type": "integer", "minimum": 0, "maximum": 1000 }, "featured": { "type": "boolean" }, "authorIds": { "type": "array", "items": { "type": "string", "minLength": 1 }, "maxItems": 10 }, "tagIds": { "type": "array", "items": { "type": "string", "minLength": 1 }, "maxItems": 20 }, "coverMediaId": { "type": "string", "nullable": true, "minLength": 1 }, "ogImageMediaId": { "type": "string", "nullable": true, "minLength": 1 }, "featureImageAlt": { "type": "string", "maxLength": 200 }, "featureImageCaption": { "type": "string", "maxLength": 500 }, "seoTitle": { "type": "string", "maxLength": 150 }, "seoDescription": { "type": "string", "maxLength": 320 }, "canonicalUrl": { "type": "string", "maxLength": 500, "format": "uri" }, "publishedAt": { "type": "string", "format": "date-time" }, "title": { "type": "string", "minLength": 1, "maxLength": 200 }, "status": { "type": "string", "enum": [ "draft", "scheduled", "published" ] } }, "additionalProperties": false }, "BlogTag": { "type": "object", "properties": { "id": { "type": "string", "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}`)." }, "object": { "type": "string", "enum": [ "blog_tag" ], "description": "String representing the object's type. Objects of the same type share the same value." }, "name": { "type": "string", "description": "Display name of the tag." }, "slug": { "type": "string", "description": "URL-friendly slug for the tag." }, "description": { "type": "string", "nullable": true, "description": "Tag description, or `null` if not set." }, "visibility": { "type": "string", "nullable": true, "description": "Tag visibility, or `null` if not set." }, "metaTitle": { "type": "string", "nullable": true, "description": "SEO meta title, or `null` if not set." }, "metaDescription": { "type": "string", "nullable": true, "description": "SEO meta description, or `null` if not set." }, "createdAt": { "type": "string", "description": "Time at which the tag was created. ISO 8601 datetime." }, "updatedAt": { "type": "string", "nullable": true, "description": "Time at which the tag was last updated, or `null` if it has never been updated. ISO 8601 datetime." } }, "required": [ "id", "object", "name", "slug", "description", "visibility", "metaTitle", "metaDescription", "createdAt", "updatedAt" ] }, "CreateTagBody": { "type": "object", "properties": { "slug": { "type": "string", "minLength": 1, "maxLength": 120, "pattern": "^[a-z0-9-]+$", "description": "URL-friendly slug for the tag. Auto-generated from `name` when omitted." }, "description": { "type": "string", "maxLength": 1000, "description": "Description for the tag. Sanitized HTML." }, "visibility": { "type": "string", "enum": [ "public", "internal" ], "description": "Tag visibility. One of `public` or `internal`." }, "metaTitle": { "type": "string", "maxLength": 150, "description": "SEO meta title for the tag page." }, "metaDescription": { "type": "string", "maxLength": 320, "description": "SEO meta description for the tag page." }, "name": { "type": "string", "minLength": 1, "maxLength": 200, "description": "The display name of the tag." } }, "required": [ "name" ], "additionalProperties": false }, "UpdateTagBody": { "type": "object", "properties": { "slug": { "type": "string", "minLength": 1, "maxLength": 120, "pattern": "^[a-z0-9-]+$", "description": "URL-friendly slug for the tag. Auto-generated from `name` when omitted." }, "description": { "type": "string", "maxLength": 1000, "description": "Description for the tag. Sanitized HTML." }, "visibility": { "type": "string", "enum": [ "public", "internal" ], "description": "Tag visibility. One of `public` or `internal`." }, "metaTitle": { "type": "string", "maxLength": 150, "description": "SEO meta title for the tag page." }, "metaDescription": { "type": "string", "maxLength": 320, "description": "SEO meta description for the tag page." }, "name": { "type": "string", "minLength": 1, "maxLength": 200, "description": "The display name of the tag." } }, "additionalProperties": false }, "Candidate": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique identifier for the candidate." }, "object": { "type": "string", "enum": [ "candidate" ], "description": "String representing the object's type." }, "email": { "type": "string", "description": "The candidate's email address." }, "displayName": { "type": "string", "nullable": true, "description": "The candidate's display name." }, "handle": { "type": "string", "nullable": true, "description": "Public-profile handle, or `null`." }, "avatarUrl": { "type": "string", "nullable": true, "description": "Avatar URL, or `null`." }, "hasResume": { "type": "boolean", "description": "Whether a resume is on file. On list rows this reflects the stored pointer; on the single-candidate detail it reflects the resolved blob (always agrees with `resume !== null`), so the two can briefly disagree if a stored file was garbage-collected." }, "createdAt": { "type": "string", "description": "ISO-8601 timestamp of when the candidate registered." }, "lastActiveAt": { "type": "string", "nullable": true, "description": "ISO-8601 timestamp of the last sign-in, or `null`." } }, "required": [ "id", "object", "email", "displayName", "handle", "avatarUrl", "hasResume", "createdAt", "lastActiveAt" ] }, "CandidateDetail": { "allOf": [ { "$ref": "#/components/schemas/Candidate" }, { "type": "object", "properties": { "profile": { "allOf": [ { "$ref": "#/components/schemas/CandidateProfile" }, { "nullable": true, "properties": { "headline": { "type": "string", "nullable": true }, "location": { "type": "string", "nullable": true }, "bio": { "type": "string", "nullable": true }, "jobSearchStatus": { "type": "string", "nullable": true }, "profileVisibility": { "type": "string", "nullable": true }, "openToRelocate": { "type": "boolean", "nullable": true }, "seniority": { "type": "array", "items": { "type": "string" } }, "skills": { "type": "array", "items": { "type": "string" } }, "workingPermits": { "type": "array", "items": { "type": "string" } }, "interestedRoles": { "type": "array", "items": { "type": "string" } } }, "required": [ "headline", "location", "bio", "jobSearchStatus", "profileVisibility", "openToRelocate", "seniority", "skills", "workingPermits", "interestedRoles" ], "description": "Admin-visible profile detail, or `null` when no profile exists." } ] }, "savedJobCount": { "type": "number", "description": "Number of jobs the candidate has saved." }, "alertCount": { "type": "number", "description": "Number of job alerts the candidate has." }, "resume": { "$ref": "#/components/schemas/CandidateResumeFile" } }, "required": [ "profile", "savedJobCount", "alertCount", "resume" ] } ] }, "CompanySummary": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique identifier for the object. Use this value as the `{id}` path parameter for the company endpoints (e.g. `GET /v1/companies/{id}`)." }, "object": { "type": "string", "enum": [ "company" ], "description": "String representing the object's type. Objects of the same type share the same value." }, "name": { "type": "string", "description": "Display name of the company." }, "slug": { "type": "string", "description": "URL-friendly slug for the company." }, "website": { "type": "string", "nullable": true, "description": "Public company website URL, or `null` if not set." }, "logoUrl": { "type": "string", "nullable": true, "description": "URL of the company logo, or `null` if no logo is set." }, "summary": { "type": "string", "nullable": true, "description": "One-line summary of the company, or `null` if not set." }, "markets": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 150, "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$" }, "description": "Canonical market slugs assigned to the company." }, "xUrl": { "type": "string", "nullable": true, "description": "X (Twitter) profile URL, or `null` if not set." }, "linkedinUrl": { "type": "string", "nullable": true, "description": "LinkedIn page URL, or `null` if not set." }, "facebookUrl": { "type": "string", "nullable": true, "description": "Facebook page URL, or `null` if not set." }, "createdAt": { "type": "string", "description": "Time at which the company was created. ISO 8601 datetime." }, "updatedAt": { "type": "string", "nullable": true, "description": "Time at which the company was last updated, or `null` if it has never been updated. ISO 8601 datetime." }, "links": { "allOf": [ { "$ref": "#/components/schemas/ResourceLinks" }, { "type": "object", "properties": { "public": { "type": "string", "nullable": true, "format": "uri", "description": "Canonical public URL for this company on the board, or `null` when no slug is set." } } } ], "description": "Public + admin URLs for this company. `public` may be `null` if the company lacks a slug." } }, "required": [ "id", "object", "name", "slug", "website", "logoUrl", "summary", "markets", "xUrl", "linkedinUrl", "facebookUrl", "createdAt", "updatedAt", "links" ] }, "CreateCompanyBody": { "type": "object", "properties": { "website": { "type": "string", "maxLength": 200, "description": "Public company website URL. Normalized to a canonical apex domain when stored." }, "summary": { "type": "string", "maxLength": 280, "description": "One-line summary of the company. Up to 280 characters." }, "description": { "type": "string", "maxLength": 25000, "description": "Long-form description of the company. Up to 25,000 characters." }, "xUrl": { "type": "string", "maxLength": 500, "description": "X (Twitter) profile URL or handle. Stored as the canonical handle." }, "linkedinUrl": { "type": "string", "maxLength": 500, "description": "LinkedIn company page URL." }, "facebookUrl": { "type": "string", "maxLength": 500, "description": "Facebook company page URL." }, "markets": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 150, "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$" }, "description": "Canonical market slugs assigned to the company. Pass an empty array to clear all markets." }, "name": { "type": "string", "minLength": 1, "maxLength": 120, "description": "The company's display name." }, "slug": { "type": "string", "minLength": 1, "maxLength": 150, "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", "description": "URL-friendly slug for the company. Auto-generated from `name` when omitted." } }, "required": [ "name" ], "additionalProperties": false }, "Company": { "allOf": [ { "$ref": "#/components/schemas/CompanySummary" }, { "type": "object", "properties": { "description": { "type": "string", "nullable": true, "description": "Long-form description of the company, or `null` if not set." }, "canBackfill": { "type": "boolean", "nullable": true, "description": "Whether automated backfill of jobs from this company is supported, or `null` if not yet evaluated." }, "jobCount": { "type": "number", "description": "Total number of jobs at this company across all statuses." }, "publishedJobCount": { "type": "number", "description": "Number of currently-published jobs at this company." } }, "required": [ "description", "canBackfill", "jobCount", "publishedJobCount" ] } ] }, "CompaniesBatchRequest": { "type": "object", "properties": { "operations": { "type": "array", "items": { "oneOf": [ { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "method": { "type": "string", "enum": [ "POST" ] }, "body": { "nullable": true }, "action": { "type": "string" }, "resourceId": { "type": "string" } }, "required": [ "id", "method" ] }, { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "method": { "type": "string", "enum": [ "PATCH" ] }, "body": { "nullable": true }, "resourceId": { "type": "string", "minLength": 1 } }, "required": [ "id", "method", "resourceId" ] }, { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "method": { "type": "string", "enum": [ "DELETE" ] }, "resourceId": { "type": "string", "minLength": 1 } }, "required": [ "id", "method", "resourceId" ] } ] }, "minItems": 1, "maxItems": 100, "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." } }, "required": [ "operations" ], "additionalProperties": false }, "FindOrCreateCompanyBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 120, "description": "The company's display name." }, "website": { "type": "string", "maxLength": 200, "description": "Public company website URL. Used to resolve to an existing company by domain before falling back to creation." }, "summary": { "type": "string", "maxLength": 280, "description": "One-line summary of the company. Up to 280 characters." }, "matchByName": { "type": "boolean", "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." }, "createIfMissing": { "type": "boolean", "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." } }, "required": [ "name" ], "additionalProperties": false }, "SearchCompaniesBody": { "type": "object", "properties": { "query": { "type": "string", "maxLength": 200, "description": "Free-text search query matched against company name. Up to 200 characters." }, "cursor": { "type": "string", "nullable": true, "minLength": 1, "description": "An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results." }, "limit": { "type": "integer", "minimum": 1, "maximum": 100, "description": "A limit on the number of objects to be returned. Limit can range between 1 and 100.", "example": 20 }, "filters": { "type": "object", "properties": { "markets": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 150, "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$" }, "maxItems": 10, "description": "Return companies assigned to any of these canonical market slugs. Up to 10 values." } }, "additionalProperties": false } }, "additionalProperties": false }, "UpdateCompanyBody": { "type": "object", "properties": { "website": { "type": "string", "maxLength": 200, "description": "Public company website URL. Normalized to a canonical apex domain when stored." }, "summary": { "type": "string", "maxLength": 280, "description": "One-line summary of the company. Up to 280 characters." }, "description": { "type": "string", "maxLength": 25000, "description": "Long-form description of the company. Up to 25,000 characters." }, "xUrl": { "type": "string", "maxLength": 500, "description": "X (Twitter) profile URL or handle. Stored as the canonical handle." }, "linkedinUrl": { "type": "string", "maxLength": 500, "description": "LinkedIn company page URL." }, "facebookUrl": { "type": "string", "maxLength": 500, "description": "Facebook company page URL." }, "markets": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 150, "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$" }, "description": "Canonical market slugs assigned to the company. Pass an empty array to clear all markets." }, "name": { "type": "string", "minLength": 1, "maxLength": 120, "description": "The company's display name." }, "slug": { "type": "string", "minLength": 1, "maxLength": 150, "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", "description": "URL-friendly slug for the company." } }, "additionalProperties": false }, "Coupon": { "type": "object", "properties": { "id": { "type": "string" }, "object": { "type": "string", "enum": [ "coupon" ] }, "name": { "type": "string", "nullable": true }, "percentOff": { "type": "number", "nullable": true }, "amountOff": { "type": "number", "nullable": true }, "currency": { "type": "string", "nullable": true }, "duration": { "type": "string" }, "durationInMonths": { "type": "number", "nullable": true }, "valid": { "type": "boolean" }, "appliesTo": { "type": "array", "nullable": true, "items": { "type": "string" } }, "timesRedeemed": { "type": "number" }, "created": { "type": "string" } }, "required": [ "id", "object", "name", "percentOff", "amountOff", "currency", "duration", "durationInMonths", "valid", "appliesTo", "timesRedeemed", "created" ] }, "CreateCouponBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1 }, "percentOff": { "type": "number", "nullable": true, "minimum": 0, "maximum": 100 }, "amountOff": { "type": "number", "nullable": true, "minimum": 0, "exclusiveMinimum": true, "description": "Fixed discount in the currency major unit (e.g. 10 for $10, 1000 for ¥1000). Required with `currency` when there is no percentOff." }, "currency": { "type": "string", "nullable": true, "minLength": 1 }, "duration": { "type": "string", "enum": [ "once", "forever", "repeating" ] }, "durationInMonths": { "type": "integer", "minimum": 0, "exclusiveMinimum": true }, "maxRedemptions": { "type": "integer", "minimum": 0, "exclusiveMinimum": true }, "redeemBy": { "type": "integer", "description": "Unix ms deadline after which the coupon cannot be redeemed." }, "appliesToPlanIds": { "type": "array", "items": { "type": "string", "minLength": 1 } } }, "required": [ "name", "duration" ], "additionalProperties": false }, "PromotionCode": { "type": "object", "properties": { "id": { "type": "string" }, "object": { "type": "string", "enum": [ "promotion_code" ] }, "code": { "type": "string" }, "couponId": { "type": "string" }, "active": { "type": "boolean" }, "created": { "type": "string" } }, "required": [ "id", "object", "code", "couponId", "active", "created" ] }, "RenameCouponBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1 } }, "required": [ "name" ], "additionalProperties": false }, "CreatePromotionCodeBody": { "type": "object", "properties": { "code": { "type": "string", "minLength": 1 }, "maxRedemptions": { "type": "integer", "minimum": 0, "exclusiveMinimum": true }, "expiresAt": { "type": "string", "format": "date-time", "description": "ISO-8601 expiry for the promotion code." }, "firstTimeTransaction": { "type": "boolean" }, "minimumAmount": { "type": "number", "minimum": 0, "exclusiveMinimum": true }, "minimumAmountCurrency": { "type": "string", "minLength": 1 } }, "required": [ "code" ], "additionalProperties": false }, "Domain": { "type": "object", "properties": { "id": { "type": "string" }, "object": { "type": "string", "enum": [ "domain" ] }, "domain": { "type": "string" }, "status": { "type": "string" }, "source": { "type": "string" }, "mode": { "type": "string", "enum": [ "direct", "edge" ] }, "connectionShape": { "type": "string", "nullable": true, "enum": [ "cname", "apexRedirect" ] }, "servedBy": { "type": "string", "nullable": true, "enum": [ "external" ] }, "statusReason": { "type": "string", "nullable": true }, "verificationToken": { "type": "string", "nullable": true }, "verificationInstructions": { "$ref": "#/components/schemas/DomainVerificationInstructions" }, "verifiedAt": { "type": "string", "nullable": true }, "isPrimary": { "type": "boolean" }, "createdAt": { "type": "string", "nullable": true } }, "required": [ "id", "object", "domain", "status", "source", "mode", "connectionShape", "servedBy", "statusReason", "verificationToken", "verificationInstructions", "verifiedAt", "isPrimary", "createdAt" ] }, "CreateDomainBody": { "type": "object", "properties": { "domain": { "type": "string", "minLength": 1, "maxLength": 253, "description": "Hostname to bind to this board, for example jobs.acme.com. Labels may contain letters, numbers, and hyphens, and may not start or end with a hyphen. The API normalizes accepted hostnames to lowercase before writing." }, "source": { "type": "string", "enum": [ "external" ] } }, "required": [ "domain" ], "additionalProperties": false }, "EmployerSubscription": { "type": "object", "properties": { "id": { "type": "string" }, "object": { "type": "string", "enum": [ "employer_subscription" ] }, "employerEmail": { "type": "string" }, "companyId": { "type": "string", "nullable": true }, "companyName": { "type": "string", "nullable": true }, "planId": { "type": "string", "nullable": true }, "planName": { "type": "string", "nullable": true }, "status": { "type": "string" }, "currentPeriodEnd": { "type": "string", "nullable": true, "description": "ISO-8601 period end, or null." }, "cancelAtPeriodEnd": { "type": "boolean" }, "createdAt": { "type": "string", "description": "ISO-8601 creation time." } }, "required": [ "id", "object", "employerEmail", "companyId", "companyName", "planId", "planName", "status", "currentPeriodEnd", "cancelAtPeriodEnd", "createdAt" ] }, "Employer": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique identifier for the employer." }, "object": { "type": "string", "enum": [ "employer" ], "description": "String representing the object's type." }, "email": { "type": "string", "description": "The employer's email address." }, "displayName": { "type": "string", "nullable": true }, "avatarUrl": { "type": "string", "nullable": true }, "emailVerifiedAt": { "type": "string", "nullable": true }, "createdAt": { "type": "string" }, "lastActiveAt": { "type": "string", "nullable": true }, "companies": { "type": "array", "items": { "allOf": [ { "$ref": "#/components/schemas/EmployerCompany" }, { "properties": { "companyId": { "type": "string" }, "companyName": { "type": "string" }, "status": { "type": "string", "description": "Membership status (e.g. `approved`)." }, "approvalSource": { "type": "string", "nullable": true, "description": "How the membership was approved (`domain_match` | `work_email_verification` | `admin` | `owner_creation`), or `null`." }, "joinedAt": { "type": "string", "description": "ISO-8601 timestamp the membership was created." } }, "required": [ "companyId", "companyName", "status", "approvalSource", "joinedAt" ] } ] }, "description": "Approved company memberships." }, "pendingClaims": { "type": "array", "items": { "$ref": "#/components/schemas/EmployerPendingClaim" }, "description": "Pending company claims (memberships awaiting approval)." } }, "required": [ "id", "object", "email", "displayName", "avatarUrl", "emailVerifiedAt", "createdAt", "lastActiveAt", "companies", "pendingClaims" ] }, "CompanyClaim": { "type": "object", "properties": { "id": { "type": "string" }, "object": { "type": "string", "enum": [ "company_claim" ] }, "companyId": { "type": "string" }, "companyName": { "type": "string" }, "employerId": { "type": "string" }, "employerEmail": { "type": "string" }, "workEmail": { "type": "string", "nullable": true }, "workEmailVerifiedAt": { "type": "string", "nullable": true }, "status": { "type": "string" }, "requestedAt": { "type": "string", "description": "ISO-8601 timestamp the claim was created." } }, "required": [ "id", "object", "companyId", "companyName", "employerId", "employerEmail", "workEmail", "workEmailVerifiedAt", "status", "requestedAt" ] }, "EmployerMembership": { "type": "object", "properties": { "id": { "type": "string" }, "object": { "type": "string", "enum": [ "employer_membership" ] }, "companyId": { "type": "string" }, "companyName": { "type": "string" }, "employerId": { "type": "string" }, "employerEmail": { "type": "string" }, "approvalSource": { "type": "string", "nullable": true, "description": "How the membership was approved (`domain_match` | `work_email_verification` | `admin` | `owner_creation`), or `null`." }, "status": { "type": "string" }, "joinedAt": { "type": "string", "description": "ISO-8601 timestamp the membership was created." } }, "required": [ "id", "object", "companyId", "companyName", "employerId", "employerEmail", "approvalSource", "status", "joinedAt" ] }, "Import": { "type": "object", "properties": { "id": { "type": "string" }, "object": { "type": "string", "enum": [ "import" ] }, "filename": { "type": "string" }, "sourceFormat": { "type": "string" }, "status": { "type": "string" }, "discoveryStatus": { "type": "string", "nullable": true }, "totalRows": { "type": "number" }, "processedRows": { "type": "number" }, "createdCount": { "type": "number" }, "updatedCount": { "type": "number" }, "skippedCount": { "type": "number" }, "errorCount": { "type": "number" }, "startedAt": { "type": "string", "nullable": true }, "completedAt": { "type": "string", "nullable": true }, "createdAt": { "type": "string" } }, "required": [ "id", "object", "filename", "sourceFormat", "status", "discoveryStatus", "totalRows", "processedRows", "createdCount", "updatedCount", "skippedCount", "errorCount", "startedAt", "completedAt", "createdAt" ] }, "ImportQuota": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "import_quota" ] }, "used": { "type": "number" }, "remaining": { "type": "number" }, "limit": { "type": "number" }, "resetAt": { "type": "string" } }, "required": [ "object", "used", "remaining", "limit", "resetAt" ] }, "ImportDetail": { "type": "object", "properties": { "id": { "type": "string" }, "object": { "type": "string", "enum": [ "import" ] }, "filename": { "type": "string" }, "sourceFormat": { "type": "string" }, "status": { "type": "string" }, "discoveryStatus": { "type": "string", "nullable": true }, "totalRows": { "type": "number" }, "processedRows": { "type": "number" }, "createdCount": { "type": "number" }, "updatedCount": { "type": "number" }, "skippedCount": { "type": "number" }, "errorCount": { "type": "number" }, "startedAt": { "type": "string", "nullable": true }, "completedAt": { "type": "string", "nullable": true }, "createdAt": { "type": "string" }, "errors": { "type": "array", "items": { "$ref": "#/components/schemas/ImportBatchError" } }, "proposedMapping": { "type": "object", "nullable": true, "properties": { "fieldMappings": { "type": "array", "items": { "type": "object", "properties": { "sourceColumn": { "type": "string" }, "targetField": { "type": "string" }, "confidence": { "type": "number" }, "notes": { "type": "string" } }, "required": [ "sourceColumn", "targetField", "confidence" ] } }, "defaults": { "type": "object", "properties": { "employmentType": { "type": "string" }, "remoteOption": { "type": "string" }, "currency": { "type": "string" }, "descriptionFormat": { "type": "string" } } }, "valueTransforms": { "type": "array", "items": { "type": "object", "properties": { "sourceColumn": { "type": "string" }, "targetField": { "type": "string" }, "map": { "type": "object", "additionalProperties": { "type": "string" } }, "fallback": { "type": "string" } }, "required": [ "sourceColumn", "targetField", "map" ] } }, "unmappedSourceColumns": { "type": "array", "items": { "type": "string" } }, "missingRequiredTargets": { "type": "array", "items": { "type": "string" } }, "warnings": { "type": "array", "items": { "type": "string" } } }, "required": [ "fieldMappings", "defaults", "valueTransforms", "unmappedSourceColumns", "missingRequiredTargets", "warnings" ], "description": "Typed, operator-reviewable mapping state. Fingerprints, cache identity, AI provenance, and extraction machinery are private." } }, "required": [ "id", "object", "filename", "sourceFormat", "status", "discoveryStatus", "totalRows", "processedRows", "createdCount", "updatedCount", "skippedCount", "errorCount", "startedAt", "completedAt", "createdAt", "errors", "proposedMapping" ] }, "ConfirmImportBody": { "type": "object", "properties": { "inlineMapping": { "type": "object", "properties": { "fieldMappings": { "type": "array", "items": { "type": "object", "properties": { "sourceColumn": { "type": "string" }, "targetField": { "type": "string" }, "confidence": { "type": "number" }, "notes": { "type": "string" } }, "required": [ "sourceColumn", "targetField", "confidence" ] } }, "defaults": { "type": "object", "properties": { "employmentType": { "type": "string" }, "remoteOption": { "type": "string" }, "currency": { "type": "string" }, "descriptionFormat": { "type": "string" } }, "default": {} }, "valueTransforms": { "type": "array", "items": { "type": "object", "properties": { "sourceColumn": { "type": "string" }, "targetField": { "type": "string" }, "map": { "type": "object", "additionalProperties": { "type": "string" } }, "fallback": { "type": "string" } }, "required": [ "sourceColumn", "targetField", "map" ] }, "default": [] } }, "required": [ "fieldMappings" ], "additionalProperties": false, "description": "A first-time or revised mapping review to persist. Omit it to accept the mapping already attached to this Import." } }, "additionalProperties": false }, "IndexingConfig": { "type": "object", "properties": { "id": { "type": "string", "enum": [ "indexing_config" ] }, "object": { "type": "string", "enum": [ "indexing_config" ] }, "enabled": { "type": "boolean", "description": "Whether Google Indexing submission is active." }, "indexNowEnabled": { "type": "boolean", "description": "Whether IndexNow (Bing/Yandex) instant indexing is enabled." }, "provisioningStatus": { "type": "string", "nullable": true, "description": "GCP provisioning state (`pending` | `provisioning` | `ready` | `error`), or null." }, "lastRunAt": { "type": "string", "nullable": true, "description": "ISO-8601 timestamp of the last submission, or null." }, "lastError": { "type": "string", "nullable": true, "description": "The last recorded error message, or null." } }, "required": [ "id", "object", "enabled", "indexNowEnabled", "provisioningStatus", "lastRunAt", "lastError" ] }, "IndexingToggleBody": { "type": "object", "properties": { "enabled": { "type": "boolean", "description": "Whether to enable the toggle." } }, "required": [ "enabled" ] }, "ReportingIntegration": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique identifier for the integration." }, "object": { "type": "string", "enum": [ "reporting_integration" ], "description": "String representing the object's type." }, "provider": { "type": "string", "enum": [ "search_console", "adsense", "tinybird", "stripe", "google_analytics" ], "description": "The reporting provider key." }, "enabled": { "type": "boolean", "description": "Whether collection is enabled for this integration." }, "connected": { "type": "boolean", "description": "Whether the connection has completed successfully." }, "connectedAt": { "type": "string", "nullable": true, "description": "ISO-8601 timestamp of when the integration was connected." } }, "required": [ "id", "object", "provider", "enabled", "connected", "connectedAt" ] }, "PatchReportingIntegrationBody": { "type": "object", "properties": { "enabled": { "type": "boolean", "description": "Whether collection is enabled for this integration." } }, "required": [ "enabled" ] }, "ReportingConnect": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "reporting_integration_connect" ], "description": "String representing the object's type." }, "provider": { "type": "string", "description": "The reporting provider key." }, "connected": { "type": "boolean", "description": "Whether the integration is already fully connected." }, "authorizationUrl": { "type": "string", "description": "OAuth providers only. The URL the user must visit to grant access." }, "siteUrl": { "type": "string", "description": "The board site URL the integration reports on." }, "redirectUrl": { "type": "string", "description": "Stripe only: the Monetization settings deep link." } }, "required": [ "object", "provider", "connected" ] }, "Invitation": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique identifier for the invitation." }, "object": { "type": "string", "enum": [ "invitation" ], "description": "String representing the object's type." }, "email": { "type": "string", "description": "The invited email address." }, "role": { "type": "string", "description": "The role the invitee will receive on accept." }, "status": { "type": "string", "description": "The invitation status: pending, expired, accepted, declined." }, "expiresAt": { "type": "string", "description": "ISO-8601 timestamp of when the invitation expires." }, "invitedByUserId": { "type": "string", "nullable": true, "description": "Identifier of the user who created the invitation." }, "createdAt": { "type": "string", "description": "ISO-8601 timestamp of when the invitation was created." } }, "required": [ "id", "object", "email", "role", "status", "expiresAt", "invitedByUserId", "createdAt" ] }, "CreateInvitationBody": { "type": "object", "properties": { "email": { "type": "string", "format": "email", "description": "The email address to invite." }, "role": { "type": "string", "enum": [ "admin", "member" ], "description": "The role the invitee receives on accept." } }, "required": [ "email", "role" ] }, "InvitationWithToken": { "allOf": [ { "$ref": "#/components/schemas/Invitation" }, { "type": "object", "properties": { "token": { "type": "string", "description": "The opaque accept token." }, "acceptUrl": { "type": "string", "description": "The full URL a recipient uses to accept the invitation." } }, "required": [ "token", "acceptUrl" ] } ] }, "UpdateInvitationBody": { "type": "object", "properties": { "role": { "type": "string", "enum": [ "admin", "member" ], "description": "The new role for the pending invitation." } }, "required": [ "role" ] }, "JobSummary": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique identifier for the object. Use this value as the `{id}` path parameter for the job endpoints (e.g. `GET /v1/jobs/{id}`)." }, "object": { "type": "string", "enum": [ "job" ], "description": "String representing the object's type. Objects of the same type share the same value." }, "title": { "type": "string", "description": "The job title." }, "slug": { "type": "string", "nullable": true, "description": "URL-friendly slug used in public board URLs, or `null` if no slug is set." }, "status": { "type": "string", "enum": [ "draft", "published", "expired", "archived" ], "description": "Current status of the job. One of `draft`, `published`, `expired`, or `archived`." }, "companyId": { "type": "string", "nullable": true, "description": "Identifier of the company the job belongs to, or `null` if no company is attached." }, "employmentType": { "type": "string", "nullable": true, "enum": [ "full_time", "part_time", "contract", "internship", "temporary", "volunteer", "other" ], "description": "Employment type of the role, or `null` if not specified." }, "remoteOption": { "type": "string", "nullable": true, "enum": [ "on_site", "hybrid", "remote" ], "description": "Whether the role is on-site, hybrid, or fully remote, or `null` if not specified." }, "seniority": { "type": "string", "nullable": true, "enum": [ "entry_level", "associate", "mid_level", "senior", "lead", "principal", "director", "executive" ], "description": "Seniority level of the role, or `null` if not specified." }, "salaryMin": { "type": "number", "nullable": true, "description": "Minimum salary in `salaryCurrency` units, or `null` if not specified." }, "salaryMax": { "type": "number", "nullable": true, "description": "Maximum salary in `salaryCurrency` units, or `null` if not specified." }, "salaryCurrency": { "type": "string", "nullable": true, "description": "Three-letter ISO 4217 currency code for the salary range, or `null` if no salary is specified." }, "salaryTimeframe": { "type": "string", "nullable": true, "enum": [ "per_year", "per_month", "per_week", "per_day", "per_hour" ], "description": "Period the salary range is quoted against, or `null` if no salary is specified." }, "isFeatured": { "type": "boolean", "description": "Whether the job appears in featured slots on the public board." }, "publishedAt": { "type": "string", "nullable": true, "description": "Time at which the job was first published, or `null` if not yet published. ISO 8601 datetime." }, "expiresAt": { "type": "string", "nullable": true, "description": "Time at which the job expires, or `null` if no expiry is set. ISO 8601 datetime." }, "createdAt": { "type": "string", "description": "Time at which the job was created. ISO 8601 datetime." }, "updatedAt": { "type": "string", "description": "Time at which the job was last updated. ISO 8601 datetime." }, "skills": { "type": "array", "items": { "type": "string" }, "description": "Canonical skill slugs assigned to the job." }, "categories": { "type": "array", "items": { "type": "string" }, "description": "Canonical category slugs assigned to the job." }, "externalId": { "type": "string", "nullable": true, "description": "External identifier supplied by the caller on create, used for deduplication via `GET /v1/jobs?externalId=...`. `null` when no external identifier was set." }, "customFieldValues": { "type": "object", "additionalProperties": { "anyOf": [ { "type": "string" }, { "type": "array", "items": { "type": "string" } }, { "type": "boolean" }, { "type": "number" } ] }, "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." }, "links": { "$ref": "#/components/schemas/AdminOnlyResourceLinks" } }, "required": [ "id", "object", "title", "slug", "status", "companyId", "employmentType", "remoteOption", "seniority", "salaryMin", "salaryMax", "salaryCurrency", "salaryTimeframe", "isFeatured", "publishedAt", "expiresAt", "createdAt", "updatedAt", "skills", "categories", "externalId", "customFieldValues", "links" ] }, "CreateJobBody": { "type": "object", "properties": { "companyId": { "type": "string", "minLength": 1, "description": "The ID of an existing company. Provide either `companyId` or `company`, not both." }, "description": { "type": "string", "minLength": 1, "maxLength": 25000, "description": "Long-form description of the role. Up to 25,000 characters." }, "slug": { "type": "string", "description": "URL-friendly slug for the job. Auto-generated from `title` when omitted." }, "employmentType": { "type": "string", "enum": [ "full_time", "part_time", "contract", "internship", "temporary", "volunteer", "other" ], "description": "Employment type of the role." }, "remoteOption": { "type": "string", "enum": [ "on_site", "hybrid", "remote" ], "description": "Whether the role is on-site, hybrid, or fully remote." }, "remotePermits": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "worldwide", "world_region", "continent", "region", "subregion", "subdivision", "country", "custom" ] }, "value": { "type": "string", "minLength": 1 } }, "required": [ "type", "value" ], "additionalProperties": false }, "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." }, "remoteTimezones": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "all", "world_region", "continent", "region", "subregion", "country", "timezone" ] }, "value": { "type": "string", "minLength": 1 }, "plusMinus": { "type": "number", "minimum": 0, "maximum": 12 } }, "required": [ "type", "value" ], "additionalProperties": false }, "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." }, "remoteSponsorship": { "type": "string", "enum": [ "yes", "no", "unknown" ], "description": "Whether the employer sponsors visas for remote candidates. One of `yes`, `no`, or `unknown`." }, "seniority": { "type": "string", "enum": [ "entry_level", "associate", "mid_level", "senior", "lead", "principal", "director", "executive" ], "description": "Seniority level of the role." }, "applicationUrl": { "type": "string", "minLength": 1, "maxLength": 2048, "description": "Where candidates apply. Accepts an HTTPS URL, a `mailto:` URI, or a bare email address (which is normalized to `mailto:` form)." }, "salaryMin": { "type": "number", "minimum": 0, "description": "Minimum salary, in `salaryCurrency` units." }, "salaryMax": { "type": "number", "minimum": 0, "description": "Maximum salary, in `salaryCurrency` units." }, "salaryCurrency": { "type": "string", "description": "Three-letter ISO 4217 currency code for `salaryMin` and `salaryMax`." }, "salaryTimeframe": { "type": "string", "enum": [ "per_year", "per_month", "per_week", "per_day", "per_hour" ], "description": "Period the `salaryMin` and `salaryMax` figures are quoted against." }, "skills": { "type": "array", "items": { "type": "string", "minLength": 1 }, "maxItems": 100, "description": "Up to 100 canonical skill slugs from `GET /v1/taxonomies/skills`. Every slug must exist in this account." }, "categories": { "type": "array", "items": { "type": "string", "minLength": 1 }, "maxItems": 100, "description": "Up to 100 canonical category slugs from `GET /v1/taxonomies/categories`. Every slug must exist in this account." }, "isFeatured": { "type": "boolean", "description": "Whether the job appears in featured slots on the public board." }, "expiresAt": { "anyOf": [ { "type": "integer", "minimum": 0 }, { "nullable": true }, { "nullable": true } ], "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." }, "publishedAt": { "type": "integer", "minimum": 0, "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." }, "educationRequirements": { "type": "array", "items": { "type": "string", "enum": [ "high_school", "associate_degree", "bachelor_degree", "professional_certificate", "postgraduate_degree", "no_requirements" ] }, "description": "Required education credentials. Each value is one of `high_school`, `associate_degree`, `bachelor_degree`, `professional_certificate`, `postgraduate_degree`, or `no_requirements`." }, "experienceMonths": { "type": "integer", "minimum": 0, "description": "Minimum required experience, expressed in months." }, "experienceInPlaceOfEducation": { "type": "boolean", "description": "If `true`, equivalent experience may substitute for the listed education requirements." }, "inOfficePeriod": { "type": "string", "enum": [ "per_week", "per_month", "per_year" ], "description": "Period denominator for `inOfficeFrequency`." }, "inOfficeFrequency": { "type": "number", "minimum": 0, "description": "How often the candidate must be in-office over `inOfficePeriod`." }, "officeLocations": { "type": "array", "items": { "$ref": "#/components/schemas/JobOfficeLocationInput" }, "description": "Physical office locations associated with the job. Each entry is forward-geocoded server-side; a country mismatch returns `400 jobs_unresolvable_location`." }, "externalId": { "type": "string", "minLength": 1, "maxLength": 255, "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." }, "customFieldValues": { "type": "object", "additionalProperties": { "anyOf": [ { "type": "string" }, { "type": "array", "items": { "type": "string" } }, { "type": "boolean" }, { "type": "number" }, { "nullable": true }, { "nullable": true } ] }, "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." }, "title": { "type": "string", "minLength": 1, "maxLength": 200, "description": "The job title." }, "company": { "$ref": "#/components/schemas/InlineCompanyInput" }, "status": { "type": "string", "enum": [ "draft", "published" ], "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." } }, "required": [ "description", "applicationUrl", "title" ], "additionalProperties": false }, "Job": { "allOf": [ { "$ref": "#/components/schemas/JobSummary" }, { "type": "object", "properties": { "links": { "allOf": [ { "$ref": "#/components/schemas/ResourceLinks" }, { "type": "object", "properties": { "public": { "type": "string", "nullable": true, "format": "uri", "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)." } } } ], "description": "Public + admin URLs for this job. `public` may be `null` if the job lacks a slug or company-slug." }, "description": { "type": "string", "nullable": true, "description": "Long-form description of the role, or `null` if not specified." }, "applicationUrl": { "type": "string", "nullable": true, "description": "Where candidates apply, or `null` if not specified. An HTTPS URL or `mailto:` URI." }, "remotePermits": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string" }, "value": { "type": "string" } }, "required": [ "type", "value" ] }, "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." }, "remoteWorldwide": { "type": "boolean", "nullable": true, "description": "Read-only: derived from `remotePermits`. `true` only when the authored selection is a single `{type:\"worldwide\"}` entry." }, "remoteTimezones": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string" }, "value": { "type": "string" }, "plusMinus": { "type": "number" } }, "required": [ "type", "value" ] }, "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." }, "remoteAllowedTzOffsets": { "type": "array", "items": { "type": "number" }, "description": "Read-only: derived from `remoteTimezones` (per-country/per-region offset fan-out). UTC hour offsets used by the job-search index." }, "remoteWorkPermitCountryCodes": { "type": "array", "items": { "type": "string" }, "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." }, "remoteWorkPermitSubdivisionCodes": { "type": "array", "items": { "type": "string" }, "description": "Read-only: derived from `remotePermits` (subdivision entries only). ISO 3166-2 codes." }, "remoteSponsorship": { "type": "string", "enum": [ "yes", "no", "unknown" ], "description": "Whether the employer sponsors visas for remote candidates. One of `yes`, `no`, or `unknown`." }, "educationRequirements": { "type": "array", "items": { "type": "string", "enum": [ "high_school", "associate_degree", "bachelor_degree", "professional_certificate", "postgraduate_degree", "no_requirements" ] }, "description": "Required education credentials. Each value is one of `high_school`, `associate_degree`, `bachelor_degree`, `professional_certificate`, `postgraduate_degree`, or `no_requirements`." }, "experienceMonths": { "type": "number", "nullable": true, "description": "Minimum required experience in months, or `null` if not specified." }, "experienceInPlaceOfEducation": { "type": "boolean", "nullable": true, "description": "If `true`, equivalent experience may substitute for the listed education requirements. `null` if not specified." }, "inOfficePeriod": { "type": "string", "nullable": true, "enum": [ "per_week", "per_month", "per_year" ], "description": "Period denominator for `inOfficeFrequency`, or `null` if not specified." }, "inOfficeFrequency": { "type": "number", "nullable": true, "description": "How often the candidate must be in-office over `inOfficePeriod`, or `null` if not specified." }, "company": { "$ref": "#/components/schemas/JobCompany" }, "officeLocations": { "type": "array", "items": { "$ref": "#/components/schemas/JobOfficeLocation" }, "description": "Physical office locations associated with the job." } }, "required": [ "description", "applicationUrl", "remotePermits", "remoteWorldwide", "remoteTimezones", "remoteAllowedTzOffsets", "remoteWorkPermitCountryCodes", "remoteWorkPermitSubdivisionCodes", "remoteSponsorship", "educationRequirements", "experienceMonths", "experienceInPlaceOfEducation", "inOfficePeriod", "inOfficeFrequency", "company", "officeLocations" ] } ] }, "BatchRequestBody": { "type": "object", "properties": { "operations": { "type": "array", "items": { "oneOf": [ { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "method": { "type": "string", "enum": [ "POST" ] }, "body": { "nullable": true }, "action": { "type": "string" }, "resourceId": { "type": "string" } }, "required": [ "id", "method" ] }, { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "method": { "type": "string", "enum": [ "PATCH" ] }, "body": { "nullable": true }, "resourceId": { "type": "string", "minLength": 1 } }, "required": [ "id", "method", "resourceId" ] }, { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "method": { "type": "string", "enum": [ "DELETE" ] }, "resourceId": { "type": "string", "minLength": 1 } }, "required": [ "id", "method", "resourceId" ] } ] }, "minItems": 1, "maxItems": 100, "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." } }, "required": [ "operations" ], "additionalProperties": false }, "SearchJobsBody": { "type": "object", "properties": { "query": { "type": "string", "maxLength": 200, "description": "Free-text search query matched against job title and description. Up to 200 characters." }, "filters": { "type": "object", "properties": { "status": { "type": "array", "items": { "type": "string", "enum": [ "draft", "published", "expired", "archived" ] }, "maxItems": 10, "description": "Only return jobs in any of the given statuses. Up to 10 values." }, "companyId": { "type": "array", "items": { "type": "string" }, "maxItems": 10, "description": "Only return jobs at any of the given company IDs. Up to 10 values." }, "remoteOption": { "type": "array", "items": { "type": "string", "enum": [ "on_site", "hybrid", "remote" ] }, "maxItems": 10, "description": "Only return jobs with any of the given remote-work options. Up to 10 values." }, "employmentType": { "type": "array", "items": { "type": "string", "enum": [ "full_time", "part_time", "contract", "internship", "temporary", "volunteer", "other" ] }, "maxItems": 10, "description": "Only return jobs with any of the given employment types. Up to 10 values." }, "seniority": { "type": "array", "items": { "type": "string", "enum": [ "entry_level", "associate", "mid_level", "senior", "lead", "principal", "director", "executive" ] }, "maxItems": 10, "description": "Only return jobs at any of the given seniority levels. Up to 10 values." }, "skills": { "type": "array", "items": { "type": "string", "minLength": 1 }, "maxItems": 10, "description": "Only return jobs tagged with any of these canonical skill slugs. Up to 10 values." }, "categories": { "type": "array", "items": { "type": "string", "minLength": 1 }, "maxItems": 10, "description": "Only return jobs tagged with any of these canonical category slugs. Up to 10 values." }, "publishedAt": { "type": "object", "properties": { "gte": { "type": "string", "format": "date-time", "description": "Only return jobs published at or after this ISO 8601 datetime." }, "lte": { "type": "string", "format": "date-time", "description": "Only return jobs published at or before this ISO 8601 datetime." } }, "additionalProperties": false, "description": "Range filter on the job's `publishedAt` timestamp." } }, "additionalProperties": false, "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." }, "cursor": { "type": "string", "minLength": 1, "description": "An opaque pagination cursor returned in the `nextCursor` field of a previous response. Pass it back to fetch the next page of results." }, "limit": { "type": "integer", "minimum": 1, "maximum": 100, "description": "A limit on the number of objects to be returned. Limit can range between 1 and 100.", "example": 20 } }, "additionalProperties": false }, "UpdateJobBody": { "type": "object", "properties": { "companyId": { "type": "string", "description": "Identifier of the company the job belongs to." }, "description": { "type": "string", "maxLength": 25000, "description": "Long-form description of the role. Up to 25,000 characters." }, "slug": { "type": "string", "description": "URL-friendly slug for the job. Auto-generated from `title` when omitted." }, "employmentType": { "type": "string", "enum": [ "full_time", "part_time", "contract", "internship", "temporary", "volunteer", "other" ], "description": "Employment type of the role." }, "remoteOption": { "type": "string", "enum": [ "on_site", "hybrid", "remote" ], "description": "Whether the role is on-site, hybrid, or fully remote." }, "remotePermits": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "worldwide", "world_region", "continent", "region", "subregion", "subdivision", "country", "custom" ] }, "value": { "type": "string", "minLength": 1 } }, "required": [ "type", "value" ], "additionalProperties": false }, "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." }, "remoteTimezones": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "all", "world_region", "continent", "region", "subregion", "country", "timezone" ] }, "value": { "type": "string", "minLength": 1 }, "plusMinus": { "type": "number", "minimum": 0, "maximum": 12 } }, "required": [ "type", "value" ], "additionalProperties": false }, "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." }, "remoteSponsorship": { "type": "string", "enum": [ "yes", "no", "unknown" ], "description": "Whether the employer sponsors visas for remote candidates. One of `yes`, `no`, or `unknown`." }, "seniority": { "type": "string", "enum": [ "entry_level", "associate", "mid_level", "senior", "lead", "principal", "director", "executive" ], "description": "Seniority level of the role." }, "applicationUrl": { "type": "string", "minLength": 1, "maxLength": 2048, "description": "Where candidates apply. Accepts an HTTPS URL, a `mailto:` URI, or a bare email address (which is normalized to `mailto:` form)." }, "salaryMin": { "type": "number", "minimum": 0, "description": "Minimum salary, in `salaryCurrency` units." }, "salaryMax": { "type": "number", "minimum": 0, "description": "Maximum salary, in `salaryCurrency` units." }, "salaryCurrency": { "type": "string", "description": "Three-letter ISO 4217 currency code for `salaryMin` and `salaryMax`." }, "salaryTimeframe": { "type": "string", "enum": [ "per_year", "per_month", "per_week", "per_day", "per_hour" ], "description": "Period the `salaryMin` and `salaryMax` figures are quoted against." }, "skills": { "type": "array", "items": { "type": "string", "minLength": 1 }, "maxItems": 100, "description": "Up to 100 canonical skill slugs from `GET /v1/taxonomies/skills`. Every slug must exist in this account." }, "categories": { "type": "array", "items": { "type": "string", "minLength": 1 }, "maxItems": 100, "description": "Up to 100 canonical category slugs from `GET /v1/taxonomies/categories`. Every slug must exist in this account." }, "isFeatured": { "type": "boolean", "description": "Whether the job appears in featured slots on the public board." }, "expiresAt": { "anyOf": [ { "type": "integer", "minimum": 0 }, { "nullable": true }, { "nullable": true } ], "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." }, "publishedAt": { "type": "integer", "minimum": 0, "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." }, "educationRequirements": { "type": "array", "items": { "type": "string", "enum": [ "high_school", "associate_degree", "bachelor_degree", "professional_certificate", "postgraduate_degree", "no_requirements" ] }, "description": "Required education credentials. Each value is one of `high_school`, `associate_degree`, `bachelor_degree`, `professional_certificate`, `postgraduate_degree`, or `no_requirements`." }, "experienceMonths": { "type": "integer", "minimum": 0, "description": "Minimum required experience, expressed in months." }, "experienceInPlaceOfEducation": { "type": "boolean", "description": "If `true`, equivalent experience may substitute for the listed education requirements." }, "inOfficePeriod": { "type": "string", "enum": [ "per_week", "per_month", "per_year" ], "description": "Period denominator for `inOfficeFrequency`." }, "inOfficeFrequency": { "type": "number", "minimum": 0, "description": "How often the candidate must be in-office over `inOfficePeriod`." }, "officeLocations": { "type": "array", "items": { "$ref": "#/components/schemas/JobOfficeLocationInput" }, "description": "Physical office locations associated with the job. Each entry is forward-geocoded server-side; a country mismatch returns `400 jobs_unresolvable_location`." }, "externalId": { "type": "string", "minLength": 1, "maxLength": 255, "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." }, "customFieldValues": { "type": "object", "additionalProperties": { "anyOf": [ { "type": "string" }, { "type": "array", "items": { "type": "string" } }, { "type": "boolean" }, { "type": "number" }, { "nullable": true }, { "nullable": true } ] }, "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." }, "title": { "type": "string", "minLength": 1, "maxLength": 200, "description": "The job title." } }, "additionalProperties": false }, "DuplicateJobBody": { "type": "object", "properties": {}, "additionalProperties": false }, "PublishJobBody": { "type": "object", "properties": { "expiresAt": { "type": "string", "nullable": true, "format": "date-time", "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." } }, "additionalProperties": false }, "Operator": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "operator" ], "description": "String representing the object's type. Objects of the same type share the same value." }, "board": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique identifier for the Board (account)." }, "slug": { "type": "string", "description": "URL slug of the Board." }, "name": { "type": "string", "description": "Display name of the Board." } }, "required": [ "id", "slug", "name" ], "description": "The Board the credential is bound to." }, "actor": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "api_key", "oauth_token", "user_session" ], "description": "How this request authenticated." }, "role": { "type": "string", "nullable": true, "description": "Current live membership role. Always `null` for API keys (Board-owned service credentials). Null for OAuth/session only when no live membership remains." }, "permissions": { "type": "array", "items": { "type": "string" }, "description": "Current effective product permissions. API keys use the key's explicit scopes; OAuth is the intersection of token scopes and the consenting member's live permissions; sessions use the member's live permissions." }, "scopes": { "type": "array", "nullable": true, "items": { "type": "string" }, "description": "Credential scopes for API keys and OAuth tokens. Always `null` for user sessions." } }, "required": [ "type", "role", "permissions", "scopes" ], "description": "The authenticated principal." } }, "required": [ "object", "board", "actor" ] }, "MediaUpload": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique identifier for the object. Use this value as the `{id}` path parameter for `GET /v1/media/{id}`." }, "object": { "type": "string", "enum": [ "media_upload" ], "description": "String representing the object's type. Objects of the same type share the same value." }, "url": { "type": "string", "nullable": true, "description": "URL where the file can be downloaded. Permanent for files served from the assets domain; a signed URL for legacy files. Always set on the upload response; may be `null` on retrieval if the underlying blob has been deleted." }, "urlExpiresAt": { "type": "string", "nullable": true, "description": "Time at which the signed `url` expires (ISO 8601 datetime), or `null` when the `url` is permanent and never expires." }, "mimeType": { "type": "string", "description": "MIME type of the uploaded file." }, "sizeBytes": { "type": "number", "description": "Size of the uploaded file, in bytes." }, "purpose": { "type": "string", "enum": [ "board_logo", "board_hero", "account_avatar", "company_logo", "blog_image" ], "description": "Resource type the file was uploaded for." } }, "required": [ "id", "object", "url", "urlExpiresAt", "mimeType", "sizeBytes", "purpose" ] }, "MediaGet": { "allOf": [ { "$ref": "#/components/schemas/MediaUpload" }, { "type": "object", "properties": { "uploadedAt": { "type": "string", "description": "Time at which the file was uploaded. ISO 8601 datetime." }, "referencedBy": { "type": "array", "items": { "type": "object", "properties": { "resourceType": { "type": "string", "description": "Type of the resource referencing this file." }, "resourceId": { "type": "string", "description": "Identifier of the resource referencing this file." } }, "required": [ "resourceType", "resourceId" ] }, "description": "Resources currently known to reference this file." } }, "required": [ "uploadedAt", "referencedBy" ] } ] }, "Member": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique identifier for the membership." }, "object": { "type": "string", "enum": [ "member" ], "description": "String representing the object's type." }, "userId": { "type": "string", "description": "Identifier of the user behind the member." }, "email": { "type": "string", "description": "The member's email address." }, "name": { "type": "string", "description": "The member's display name." }, "avatarUrl": { "type": "string", "nullable": true, "description": "URL of the member's avatar, or `null` if none is set." }, "role": { "type": "string", "description": "The member's role in the account." }, "suspended": { "type": "boolean", "description": "Whether the member is currently suspended." }, "joinedAt": { "type": "string", "description": "ISO-8601 timestamp of when the member joined the account." }, "isPrimaryOwner": { "type": "boolean", "description": "Whether the member is the account primary owner." } }, "required": [ "id", "object", "userId", "email", "name", "avatarUrl", "role", "suspended", "joinedAt", "isPrimaryOwner" ] }, "TransferOwnershipBody": { "type": "object", "properties": { "newOwnerUserId": { "type": "string", "minLength": 1, "description": "The user ID of the member who will become the primary owner." } }, "required": [ "newOwnerUserId" ] }, "UpdateMemberBody": { "type": "object", "properties": { "role": { "type": "string", "enum": [ "owner", "admin", "member" ], "description": "The new role. Only an owner may set `owner`; the primary owner’s role is immutable (use transfer-ownership)." } }, "required": [ "role" ] }, "CandidatePaywall": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "candidate_paywall" ] }, "enabled": { "type": "boolean" }, "previewCount": { "type": "integer", "minimum": 1, "maximum": 500 }, "lockHeading": { "type": "string", "minLength": 1, "maxLength": 120 }, "lockDescription": { "type": "string", "maxLength": 600 }, "buttonText": { "type": "string", "minLength": 1, "maxLength": 60 }, "disclaimerText": { "type": "string", "maxLength": 200 }, "currency": { "type": "string", "minLength": 3, "maxLength": 3, "pattern": "^[a-z]{3}$", "description": "ISO 4217 currency code, lowercase (e.g. usd)." }, "perMonthLabel": { "type": "string", "minLength": 1, "maxLength": 60 }, "savingsTemplate": { "type": "string", "maxLength": 120 }, "offers": { "type": "array", "items": { "$ref": "#/components/schemas/CandidatePaywallOffer" } } }, "required": [ "object", "enabled", "previewCount", "lockHeading", "lockDescription", "buttonText", "disclaimerText", "currency", "perMonthLabel", "savingsTemplate", "offers" ] }, "PutCandidatePaywallBody": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "candidate_paywall" ] }, "enabled": { "type": "boolean" }, "previewCount": { "type": "integer", "minimum": 1, "maximum": 500 }, "lockHeading": { "type": "string", "minLength": 1, "maxLength": 120 }, "lockDescription": { "type": "string", "maxLength": 600 }, "buttonText": { "type": "string", "minLength": 1, "maxLength": 60 }, "disclaimerText": { "type": "string", "maxLength": 200 }, "currency": { "type": "string", "minLength": 3, "maxLength": 3, "pattern": "^[A-Za-z]{3}$" }, "perMonthLabel": { "type": "string", "minLength": 1, "maxLength": 60 }, "savingsTemplate": { "type": "string", "maxLength": 120 }, "offers": { "type": "array", "items": { "type": "object", "properties": { "key": { "type": "string", "enum": [ "daily", "weekly", "monthly", "quarterly", "yearly", "lifetime" ] }, "enabled": { "type": "boolean" }, "amountCents": { "type": "integer", "minimum": 0 }, "isDefault": { "type": "boolean" }, "label": { "type": "string", "maxLength": 60 }, "billingLabel": { "type": "string", "maxLength": 60 }, "kind": { "type": "string", "enum": [ "recurring", "lifetime" ] }, "displayOrder": { "type": "integer", "minimum": 0 }, "intervalUnit": { "type": "string", "nullable": true, "enum": [ "day", "week", "month", "year" ] }, "intervalCount": { "type": "integer", "nullable": true, "minimum": 0, "exclusiveMinimum": true } }, "required": [ "key", "enabled", "amountCents", "isDefault" ] } } }, "required": [ "enabled", "previewCount", "lockHeading", "lockDescription", "buttonText", "disclaimerText", "currency", "perMonthLabel", "savingsTemplate", "offers" ], "additionalProperties": false }, "CandidatePaywallSubscription": { "type": "object", "properties": { "id": { "type": "string", "description": "Cavuno candidate access grant ID." }, "object": { "type": "string", "enum": [ "candidate_paywall_subscription" ] }, "candidateId": { "type": "string", "description": "Board user / Candidate Cavuno ID (boardUsers id)." }, "email": { "type": "string" }, "displayName": { "type": "string" }, "kind": { "type": "string", "enum": [ "recurring", "lifetime" ] }, "offerKey": { "type": "string", "enum": [ "daily", "weekly", "monthly", "quarterly", "yearly", "lifetime" ], "description": "One of: daily, weekly, monthly, quarterly, yearly, lifetime." }, "status": { "type": "string", "enum": [ "pending", "active", "trialing", "expired", "past_due", "unpaid", "incomplete", "incomplete_expired", "canceled" ] }, "amountCents": { "type": "integer", "minimum": 0 }, "currency": { "type": "string", "pattern": "^[a-z]{3}$", "description": "ISO 4217 currency code, lowercase (e.g. usd)." }, "currentPeriodStart": { "type": "string", "nullable": true, "format": "date-time", "description": "ISO-8601 or null." }, "currentPeriodEnd": { "type": "string", "nullable": true, "format": "date-time", "description": "ISO-8601 or null." }, "cancelAtPeriodEnd": { "type": "boolean" }, "activatedAt": { "type": "string", "nullable": true, "format": "date-time", "description": "ISO-8601 or null." }, "canceledAt": { "type": "string", "nullable": true, "format": "date-time", "description": "ISO-8601 or null." }, "createdAt": { "type": "string", "format": "date-time", "description": "ISO-8601 creation time." } }, "required": [ "id", "object", "candidateId", "email", "displayName", "kind", "offerKey", "status", "amountCents", "currency", "currentPeriodStart", "currentPeriodEnd", "cancelAtPeriodEnd", "activatedAt", "canceledAt", "createdAt" ] }, "AdminPlan": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique identifier for the plan." }, "object": { "type": "string", "enum": [ "plan" ] }, "name": { "type": "string" }, "description": { "type": "string", "nullable": true }, "kind": { "type": "string" }, "billingInterval": { "type": "string", "nullable": true, "enum": [ "month", "year" ], "description": "Subscription billing interval. Required for kind=subscription." }, "purpose": { "type": "string", "enum": [ "job_posting", "talent_access" ], "description": "Whether the plan grants job-posting or talent-access entitlement." }, "isPublic": { "type": "boolean" }, "isRecommended": { "type": "boolean" }, "isArchived": { "type": "boolean" }, "displayOrder": { "type": "number", "nullable": true }, "price": { "$ref": "#/components/schemas/PlanPrice" }, "features": { "type": "array", "items": { "$ref": "#/components/schemas/PlanFeature" } } }, "required": [ "id", "object", "name", "description", "kind", "billingInterval", "purpose", "isPublic", "isRecommended", "isArchived", "displayOrder", "price", "features" ] }, "CreatePlanBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "description": "Display name for the plan." }, "description": { "type": "string", "description": "Optional plan description." }, "kind": { "type": "string", "enum": [ "free", "one_time", "bundle", "subscription" ], "description": "Plan billing kind." }, "billingInterval": { "type": "string", "enum": [ "month", "year" ], "description": "Subscription billing interval. Required for kind=subscription." }, "purpose": { "type": "string", "enum": [ "job_posting", "talent_access" ], "description": "Whether the plan grants job-posting or talent-access entitlement." }, "isPublic": { "type": "boolean", "description": "Whether the plan is publicly listed. Defaults to false." }, "isRecommended": { "type": "boolean" }, "displayOrder": { "type": "integer" } }, "required": [ "name", "kind" ], "additionalProperties": false }, "UpdatePlanBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1 }, "description": { "type": "string" }, "isPublic": { "type": "boolean", "description": "Publish/unpublish the plan." }, "isRecommended": { "type": "boolean" }, "isArchived": { "type": "boolean", "description": "Archive the plan (soft-delete). There is no hard DELETE." }, "displayOrder": { "type": "integer" } }, "additionalProperties": false }, "PlanFeatureValue": { "type": "object", "properties": { "key": { "type": "string", "enum": [ "jobs.max_active", "jobs.duration_days", "jobs.featured_slots", "jobs.feature_selection_mode", "talent.profile_unlocks", "talent.messages_sent" ] }, "value": { "type": "string" } }, "required": [ "key", "value" ] }, "SetPlanFeaturesBody": { "type": "object", "properties": { "features": { "type": "array", "items": { "type": "object", "properties": { "key": { "type": "string", "enum": [ "jobs.max_active", "jobs.duration_days", "jobs.featured_slots", "jobs.feature_selection_mode", "talent.profile_unlocks", "talent.messages_sent" ] }, "value": { "type": "string" } }, "required": [ "key", "value" ] }, "description": "Full replacement set of typed Cavuno capability key/value pairs for the plan." } }, "required": [ "features" ], "additionalProperties": false }, "SetPlanPriceBody": { "type": "object", "properties": { "currency": { "type": "string", "minLength": 3, "maxLength": 3, "description": "ISO 4217 currency code (e.g. usd)." }, "amountCents": { "type": "integer", "minimum": 0, "description": "Unit amount in the smallest currency unit." } }, "required": [ "currency", "amountCents" ], "additionalProperties": false }, "PlanPrice": { "type": "object", "nullable": true, "properties": { "currency": { "type": "string", "description": "ISO 4217 currency code, lowercase." }, "amountCents": { "type": "integer", "description": "Unit amount in the smallest currency unit." } }, "required": [ "currency", "amountCents" ], "description": "The plan single active price, or null when no price has been set." }, "Redirect": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique identifier for the redirect." }, "object": { "type": "string", "enum": [ "redirect" ], "description": "String representing the object's type. Objects of the same type share the same value." }, "fromPath": { "type": "string", "description": "Source path matched by this redirect." }, "toPath": { "type": "string", "description": "Destination path or URL." }, "statusCode": { "anyOf": [ { "type": "number", "enum": [ 301 ] }, { "type": "number", "enum": [ 302 ] } ], "description": "HTTP status code used when redirecting." }, "createdAt": { "type": "string", "description": "Time at which the redirect was created. ISO 8601 datetime." } }, "required": [ "id", "object", "fromPath", "toPath", "statusCode", "createdAt" ] }, "CreateRedirectBody": { "type": "object", "properties": { "fromPath": { "type": "string", "minLength": 1, "description": "Source path to match, for example `/old-careers`." }, "toPath": { "type": "string", "minLength": 1, "description": "Destination path or URL, for example `/jobs`." }, "statusCode": { "anyOf": [ { "type": "number", "enum": [ 301 ] }, { "type": "number", "enum": [ 302 ] } ], "default": 301, "description": "HTTP status code. One of `301` or `302`. Defaults to `301`." } }, "required": [ "fromPath", "toPath" ], "additionalProperties": false }, "RedirectsBatchRequest": { "type": "object", "properties": { "operations": { "type": "array", "items": { "oneOf": [ { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "method": { "type": "string", "enum": [ "POST" ] }, "body": { "nullable": true }, "action": { "type": "string" }, "resourceId": { "type": "string" } }, "required": [ "id", "method" ] }, { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "method": { "type": "string", "enum": [ "PATCH" ] }, "body": { "nullable": true }, "resourceId": { "type": "string", "minLength": 1 } }, "required": [ "id", "method", "resourceId" ] }, { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "method": { "type": "string", "enum": [ "DELETE" ] }, "resourceId": { "type": "string", "minLength": 1 } }, "required": [ "id", "method", "resourceId" ] } ] }, "minItems": 1, "maxItems": 100, "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." } }, "required": [ "operations" ], "additionalProperties": false }, "UpdateRedirectBody": { "type": "object", "properties": { "fromPath": { "type": "string", "minLength": 1, "description": "Source path to match, for example `/old-careers`." }, "toPath": { "type": "string", "minLength": 1, "description": "Destination path or URL, for example `/jobs`." }, "statusCode": { "anyOf": [ { "type": "number", "enum": [ 301 ] }, { "type": "number", "enum": [ 302 ] } ], "description": "HTTP status code. One of `301` or `302`." } }, "additionalProperties": false }, "AdminSalesLedPlan": { "type": "object", "properties": { "id": { "type": "string", "description": "Cavuno salesLedEmployerPlans ID." }, "object": { "type": "string", "enum": [ "sales_led_plan" ] }, "name": { "type": "string" }, "description": { "type": "string" }, "priceText": { "type": "string" }, "ctaText": { "type": "string" }, "ctaDestination": { "type": "string" }, "featuredBullets": { "type": "array", "items": { "type": "string" } }, "isPublic": { "type": "boolean" }, "displayOrder": { "type": "integer" }, "createdAt": { "type": "string", "description": "ISO-8601 creation timestamp." } }, "required": [ "id", "object", "name", "description", "priceText", "ctaText", "ctaDestination", "featuredBullets", "isPublic", "displayOrder", "createdAt" ] }, "CreateSalesLedPlanBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1 }, "description": { "type": "string", "minLength": 1 }, "priceText": { "type": "string", "minLength": 1 }, "ctaText": { "type": "string", "minLength": 1 }, "ctaDestination": { "type": "string", "minLength": 1, "description": "Email address or URL. Bare emails become mailto:; bare domains become https://." }, "featuredBullets": { "type": "array", "items": { "type": "string" }, "maxItems": 5, "description": "Up to five feature bullets shown on the pricing card." }, "isPublic": { "type": "boolean", "description": "Whether the plan is shown on the public employer pricing page." }, "displayOrder": { "type": "integer", "minimum": 0, "description": "Sort order among active sales-led plans (lower first)." } }, "required": [ "name", "description", "priceText", "ctaText", "ctaDestination", "featuredBullets", "isPublic", "displayOrder" ], "additionalProperties": false }, "ReorderSalesLedPlansBody": { "type": "object", "properties": { "orders": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "minLength": 1, "description": "Cavuno sales-led plan ID from list/create." }, "displayOrder": { "type": "integer", "minimum": 0 } }, "required": [ "id", "displayOrder" ], "additionalProperties": false }, "description": "Complete active set: every non-archived plan id exactly once, with unique displayOrder values." } }, "required": [ "orders" ], "additionalProperties": false }, "UpdateSalesLedPlanBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1 }, "description": { "type": "string", "minLength": 1 }, "priceText": { "type": "string", "minLength": 1 }, "ctaText": { "type": "string", "minLength": 1 }, "ctaDestination": { "type": "string", "minLength": 1, "description": "Email address or URL. Bare emails become mailto:; bare domains become https://." }, "featuredBullets": { "type": "array", "items": { "type": "string" }, "maxItems": 5, "description": "Up to five feature bullets shown on the pricing card." }, "isPublic": { "type": "boolean", "description": "Whether the plan is shown on the public employer pricing page." }, "displayOrder": { "type": "integer", "minimum": 0, "description": "Sort order among active sales-led plans (lower first)." } }, "required": [ "name", "description", "priceText", "ctaText", "ctaDestination", "featuredBullets", "isPublic", "displayOrder" ], "additionalProperties": false }, "Settings": { "type": "object", "properties": { "id": { "type": "string" }, "object": { "type": "string", "enum": [ "settings" ] }, "accountId": { "type": "string" }, "name": { "type": "string" }, "slug": { "type": "string" }, "primaryDomainId": { "type": "string", "nullable": true }, "logoUrl": { "type": "string", "nullable": true }, "heroUrl": { "type": "string", "nullable": true }, "config": { "$ref": "#/components/schemas/OperatorSettingsConfig" }, "createdAt": { "type": "string" }, "updatedAt": { "type": "string" } }, "required": [ "id", "object", "accountId", "name", "slug", "primaryDomainId", "logoUrl", "heroUrl", "config", "createdAt", "updatedAt" ], "additionalProperties": false }, "PatchSettingsBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Display name of the board." }, "slug": { "type": "string", "minLength": 1, "maxLength": 120, "description": "URL slug of the board. Lowercase alphanumeric and hyphens; reserved values (e.g. `admin`, `api`) are rejected." }, "primaryDomainId": { "type": "string", "description": "Identifier of the custom domain to use as the primary public URL." }, "logoMediaId": { "type": "string", "description": "Cavuno media ID returned by `POST /v1/media/upload` with `purpose=board_logo`." }, "heroMediaId": { "type": "string", "description": "Cavuno media ID returned by `POST /v1/media/upload` with `purpose=board_hero`." }, "passwordProtectionEnabled": { "type": "boolean", "description": "Whether the board sits behind a password gate. Use `POST /v1/settings/password-protection` to set the actual password before enabling." }, "jobAlertsEnabled": { "type": "boolean", "description": "Whether candidates can subscribe to email alerts for new jobs." }, "candidatesEnabled": { "type": "boolean", "description": "Whether candidate profiles are enabled on the board." }, "employersEnabled": { "type": "boolean", "description": "Whether employer self-serve flows are enabled." }, "blogEnabled": { "type": "boolean", "description": "Whether the public blog is exposed." }, "impressumEnabled": { "type": "boolean", "description": "Whether the legal Impressum page is exposed (required in some jurisdictions)." }, "requireApprovalFreeJobs": { "type": "boolean", "description": "Whether jobs posted by employers from the free tier require admin approval before they appear on the public board." }, "requireApprovalAggregatedJobs": { "type": "boolean", "description": "Whether aggregated jobs (e.g. those sourced or imported from upstream sources) require admin approval before they appear on the public board." }, "registrationWallEnabled": { "type": "boolean", "description": "Whether visitors must sign in to view jobs." }, "nativeApplicationsEnabled": { "type": "boolean", "description": "Whether the board's built-in ATS receives applications. When `false` (external-applications-only board), posting surfaces require an external `applicationUrl` and `POST /boards/:identifier/jobs/:jobSlug/apply` rejects with `applications_native_disabled`. Turning this off UNPUBLISHES every published native-apply job (those with no external `applicationUrl`) back to draft via an asynchronous batched drain. Expect published job counts to shrink over the following seconds. Nothing is deleted, and re-enabling does NOT republish the drafted jobs. Absent means `true`." }, "applicantMessagingEnabled": { "type": "boolean", "description": "Whether applicant↔employer messaging is enabled. When `false`, the `me/conversations` route family rejects with `messaging_disabled` and new-message emails are suppressed. Absent means `true`." }, "talentDirectoryEnabled": { "type": "boolean", "description": "Legacy shorthand for the talent directory. `true` maps to `talentDirectoryVisibility: \"public\"`; `false` maps to `\"off\"`. Prefer the tri-state field. Providing both with conflicting values returns `settings_conflicting_fields`." }, "talentDirectoryVisibility": { "type": "string", "enum": [ "off", "public", "employers_only" ], "description": "Talent directory access mode: `off` (hidden), `public` (anyone), or `employers_only` (approved employers). Canonical field; supersedes `talentDirectoryEnabled`." }, "requireCookieConsent": { "type": "boolean", "description": "Whether the public board shows a cookie consent banner before non-essential tracking runs." }, "cookieBannerTitle": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Title shown on the cookie consent banner. 1–200 characters." }, "cookieBannerDescription": { "type": "string", "minLength": 1, "maxLength": 500, "description": "Body copy shown on the cookie consent banner. 1–500 characters." }, "cookieBannerRejectLabel": { "type": "string", "minLength": 1, "maxLength": 80, "description": "Reject-button label on the cookie consent banner. 1–80 characters." }, "cookieBannerAcceptLabel": { "type": "string", "minLength": 1, "maxLength": 80, "description": "Accept-button label on the cookie consent banner. 1–80 characters." }, "cookieBannerManageLabel": { "type": "string", "minLength": 1, "maxLength": 80, "description": "Preferences/manage-button label on the cookie consent banner. 1–80 characters." }, "showCavunoBranding": { "type": "boolean", "description": "Whether the Cavuno-branded footer is displayed on the public board. Plan-gated; lower-tier plans cannot disable this." }, "defaultJobDurationDays": { "type": "integer", "minimum": 0, "exclusiveMinimum": true, "description": "Default expiry, in days, applied to newly published jobs when no `expiresAt` is supplied." }, "contactEmail": { "anyOf": [ { "type": "string", "maxLength": 320, "format": "email" }, { "type": "string", "enum": [ "" ] }, { "nullable": true }, { "nullable": true } ], "description": "Public contact email shown on the board. Pass `null` to clear." }, "companyLegalName": { "anyOf": [ { "type": "string", "maxLength": 200 }, { "type": "string", "enum": [ "" ] }, { "nullable": true }, { "nullable": true } ], "description": "Legal name of the entity operating the board. Pass `null` to clear." }, "companyAddress": { "anyOf": [ { "type": "string", "maxLength": 500 }, { "type": "string", "enum": [ "" ] }, { "nullable": true }, { "nullable": true } ], "description": "Postal address of the entity operating the board. Pass `null` to clear." }, "companyWebsiteUrl": { "anyOf": [ { "type": "string", "maxLength": 500 }, { "type": "string", "enum": [ "" ] }, { "nullable": true }, { "nullable": true } ], "description": "Public company website URL. Pass `null` to clear." }, "companyXHandle": { "anyOf": [ { "type": "string", "maxLength": 500 }, { "type": "string", "enum": [ "" ] }, { "nullable": true }, { "nullable": true } ], "description": "Company X (Twitter) handle or profile URL. Pass `null` to clear." }, "companyFacebookUrl": { "anyOf": [ { "type": "string", "maxLength": 500 }, { "type": "string", "enum": [ "" ] }, { "nullable": true }, { "nullable": true } ], "description": "Company Facebook page URL. Pass `null` to clear." }, "companyLinkedinUrl": { "anyOf": [ { "type": "string", "maxLength": 500 }, { "type": "string", "enum": [ "" ] }, { "nullable": true }, { "nullable": true } ], "description": "Company LinkedIn page URL. Pass `null` to clear." }, "talentNavLabel": { "type": "string", "minLength": 1, "maxLength": 50, "description": "Label shown for the talent directory in the public navigation. 1–50 characters." }, "passwordProtectionMessage": { "anyOf": [ { "type": "string", "maxLength": 500 }, { "type": "string", "enum": [ "" ] }, { "nullable": true }, { "nullable": true } ], "description": "Custom copy displayed on the password gate. Up to 500 characters. Pass `null` to clear." } }, "additionalProperties": false }, "SettingsAdsenseBody": { "type": "object", "properties": { "adsenseEnabled": { "type": "boolean", "description": "Whether AdSense placements are rendered on the public board." }, "adsenseClientId": { "anyOf": [ { "type": "string", "maxLength": 25, "pattern": "^ca-pub-\\d{16}$" }, { "type": "string", "enum": [ "" ] }, { "nullable": true }, { "nullable": true } ], "description": "AdSense publisher ID in `ca-pub-XXXXXXXXXXXXXXXX` format. Pass an empty string or `null` to clear." }, "adsenseSlots": { "type": "object", "additionalProperties": { "$ref": "#/components/schemas/SettingsAdsenseSlot" }, "description": "Map of placement key to slot configuration. Placement keys are lowercase alphanumeric with `-`, `_`, `.`, or `:`." }, "adsTxt": { "anyOf": [ { "type": "string", "maxLength": 2000 }, { "type": "string", "enum": [ "" ] }, { "nullable": true }, { "nullable": true } ], "description": "Contents to serve from `/ads.txt`. Up to 2,000 characters. Pass an empty string or `null` to clear." } }, "additionalProperties": false }, "JobFormConfig": { "type": "object", "properties": { "sponsorship": { "type": "object", "properties": { "visible": { "type": "boolean" } }, "required": [ "visible" ] }, "salary": { "type": "object", "properties": { "visible": { "type": "boolean" }, "required": { "type": "boolean" }, "minBound": { "type": "number" }, "maxBound": { "type": "number" }, "allowedCurrencies": { "type": "array", "items": { "type": "string" } } }, "required": [ "visible" ] }, "seniority": { "type": "object", "properties": { "visible": { "type": "boolean" }, "required": { "type": "boolean" }, "allowedOptions": { "type": "array", "items": { "type": "string" } } }, "required": [ "visible" ] }, "workArrangement": { "type": "object", "properties": { "allowedOptions": { "type": "array", "items": { "type": "string" } } }, "required": [ "allowedOptions" ] }, "employmentType": { "type": "object", "properties": { "allowedOptions": { "type": "array", "items": { "type": "string" } } }, "required": [ "allowedOptions" ] }, "location": { "type": "object", "properties": { "visible": { "type": "boolean" }, "allowedCountries": { "type": "array", "items": { "type": "string" } } }, "required": [ "visible" ] }, "customFields": { "type": "array", "items": { "$ref": "#/components/schemas/CustomFieldDefinition" }, "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." } } }, "JobFormCustomFieldsBody": { "type": "object", "properties": { "customFields": { "type": "array", "items": { "$ref": "#/components/schemas/CustomFieldDefinition" }, "description": "Full replacement list of custom field definitions, in display order. Empty array removes all. Changing `type` on an existing `key` is rejected (422); delete + recreate instead. Renaming a key is delete+add and orphans per-job values under the old key." } }, "required": [ "customFields" ], "additionalProperties": false }, "SettingsPasswordProtectionBody": { "type": "object", "properties": { "password": { "type": "string", "minLength": 8, "description": "Plaintext password used to gate the public board. Must be at least 8 characters. Stored hashed and encrypted server-side." } }, "required": [ "password" ], "additionalProperties": false }, "Subscriber": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique identifier for the subscriber." }, "object": { "type": "string", "enum": [ "subscriber" ], "description": "String representing the object's type." }, "email": { "type": "string", "description": "The subscriber's email address." }, "confirmedAt": { "type": "string", "nullable": true, "description": "ISO-8601 timestamp of double-opt-in confirmation, or `null`." }, "waitlistedAt": { "type": "string", "nullable": true, "description": "ISO-8601 timestamp of when the subscriber was waitlisted." }, "unsubscribedAt": { "type": "string", "nullable": true, "description": "ISO-8601 timestamp of when the subscriber unsubscribed." }, "createdAt": { "type": "string", "description": "ISO-8601 timestamp of when the subscriber was created." } }, "required": [ "id", "object", "email", "confirmedAt", "waitlistedAt", "unsubscribedAt", "createdAt" ] }, "SubscriberCount": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "subscriber_count" ] }, "confirmed": { "type": "number", "description": "The number of confirmed subscribers for the account." } }, "required": [ "object", "confirmed" ] }, "SubscriberDetail": { "allOf": [ { "$ref": "#/components/schemas/Subscriber" }, { "type": "object", "properties": { "lastSentAt": { "type": "string", "nullable": true, "description": "ISO-8601 timestamp of the most recent alert dispatch, or `null`." }, "alerts": { "type": "array", "items": { "allOf": [ { "$ref": "#/components/schemas/Alert" }, { "properties": { "id": { "type": "string", "description": "Unique identifier for the alert." }, "object": { "type": "string", "enum": [ "alert" ], "description": "String representing the object's type." }, "subscriberId": { "type": "string", "description": "Identifier of the subscriber that owns this alert." }, "filters": { "nullable": true, "description": "The job-filter criteria the alert matches against." }, "frequency": { "type": "string", "description": "Delivery cadence: `instant`, `daily`, or `weekly`." }, "isActive": { "type": "boolean", "description": "Whether the alert is currently active." }, "lastSentAt": { "type": "string", "nullable": true, "description": "ISO-8601 timestamp of the last dispatch, or `null`." }, "createdAt": { "type": "string", "description": "ISO-8601 timestamp of when the alert was created." } }, "required": [ "id", "object", "subscriberId", "frequency", "isActive", "lastSentAt", "createdAt" ] } ] }, "description": "The subscriber's alerts." } }, "required": [ "lastSentAt", "alerts" ] } ] }, "Alert": { "type": "object", "properties": { "id": { "type": "string", "description": "Job-alert preference ID. Also the path key." }, "object": { "type": "string", "enum": [ "alert" ] }, "label": { "type": "string", "nullable": true }, "frequency": { "type": "string", "enum": [ "weekly" ] }, "isActive": { "type": "boolean" }, "filters": { "type": "object", "properties": { "jobFunctions": { "type": "array", "items": { "type": "string" } }, "seniorityLevels": { "type": "array", "items": { "type": "string" } }, "remoteOptions": { "type": "array", "items": { "type": "string" } }, "placeIds": { "type": "array", "items": { "type": "string" } }, "salaryMin": { "type": "number", "nullable": true }, "salaryMax": { "type": "number", "nullable": true }, "salaryCurrency": { "type": "string", "nullable": true } }, "required": [ "jobFunctions", "seniorityLevels", "remoteOptions", "placeIds", "salaryMin", "salaryMax", "salaryCurrency" ] }, "lastSentAt": { "type": "string", "nullable": true, "format": "date-time", "description": "When this alert last dispatched a digest, or null." } }, "required": [ "id", "object", "label", "frequency", "isActive", "filters", "lastSentAt" ] }, "Category": { "type": "object", "properties": { "id": { "type": "string" }, "object": { "type": "string", "enum": [ "category" ] }, "name": { "type": "string" }, "slug": { "type": "string" }, "aliasSlugs": { "type": "array", "items": { "type": "string" } }, "sourceLocale": { "type": "string", "nullable": true }, "parentId": { "type": "string", "nullable": true }, "createdAt": { "type": "string" }, "children": { "type": "array", "items": { "nullable": true } } }, "required": [ "id", "object", "name", "slug", "aliasSlugs", "sourceLocale", "parentId", "createdAt" ] }, "CreateCategoryBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200 }, "slug": { "type": "string", "minLength": 1, "maxLength": 120, "pattern": "^[a-z0-9-]+$" }, "parentId": { "type": "string", "minLength": 1 }, "aliasSlugs": { "type": "array", "items": { "type": "string", "minLength": 1 }, "maxItems": 20 }, "sourceLocale": { "type": "string", "minLength": 2, "maxLength": 16 } }, "required": [ "name" ], "additionalProperties": false }, "UpdateCategoryBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200 }, "slug": { "type": "string", "minLength": 1, "maxLength": 120, "pattern": "^[a-z0-9-]+$" }, "parentId": { "anyOf": [ { "type": "string", "minLength": 1 }, { "nullable": true }, { "nullable": true } ] }, "sourceLocale": { "type": "string", "minLength": 2, "maxLength": 16 } }, "additionalProperties": false }, "AddCategoryAliasesBody": { "type": "object", "properties": { "aliases": { "type": "array", "items": { "type": "string", "minLength": 1 }, "minItems": 1, "maxItems": 20 } }, "required": [ "aliases" ], "additionalProperties": false }, "Market": { "type": "object", "properties": { "id": { "type": "string" }, "object": { "type": "string", "enum": [ "market" ] }, "name": { "type": "string" }, "slug": { "type": "string" }, "aliasSlugs": { "type": "array", "items": { "type": "string" } }, "sourceLocale": { "type": "string", "nullable": true }, "createdAt": { "type": "string" } }, "required": [ "id", "object", "name", "slug", "aliasSlugs", "sourceLocale", "createdAt" ] }, "CreateMarketBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200 }, "slug": { "type": "string", "minLength": 1, "maxLength": 120, "pattern": "^[a-z0-9-]+$" }, "aliasSlugs": { "type": "array", "items": { "type": "string", "minLength": 1 }, "maxItems": 20 }, "sourceLocale": { "type": "string", "minLength": 2, "maxLength": 16 } }, "required": [ "name" ], "additionalProperties": false }, "UpdateMarketBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200 }, "slug": { "type": "string", "minLength": 1, "maxLength": 120, "pattern": "^[a-z0-9-]+$" }, "sourceLocale": { "type": "string", "minLength": 2, "maxLength": 16 } }, "additionalProperties": false }, "AddMarketAliasesBody": { "type": "object", "properties": { "aliases": { "type": "array", "items": { "type": "string", "minLength": 1 }, "minItems": 1, "maxItems": 20 } }, "required": [ "aliases" ], "additionalProperties": false }, "RemotePermitTaxonomyEntry": { "type": "object", "properties": { "type": { "type": "string", "description": "Discriminator. One of: `worldwide`, `world_region`, `continent`, `region`, `subregion`, `custom`, `country`, `subdivision`." }, "value": { "type": "string", "description": "Canonical value for the type. ISO 3166-1 alpha-2 for `country`, ISO 3166-2 for `subdivision`, etc." }, "label": { "type": "string", "description": "Human-readable display label." } }, "required": [ "type", "value", "label" ] }, "RemoteTimezoneTaxonomyEntry": { "type": "object", "properties": { "type": { "type": "string", "description": "Discriminator. One of: `all`, `world_region`, `continent`, `region`, `subregion`, `country`, `timezone`." }, "value": { "type": "string", "description": "Canonical value for the type. ISO 3166-1 alpha-2 for `country`, IANA name (e.g. `Europe/London`) for `timezone`, etc." }, "label": { "type": "string", "description": "Human-readable display label." } }, "required": [ "type", "value", "label" ] }, "Skill": { "type": "object", "properties": { "id": { "type": "string" }, "object": { "type": "string", "enum": [ "skill" ] }, "name": { "type": "string" }, "slug": { "type": "string" }, "aliasSlugs": { "type": "array", "items": { "type": "string" } }, "sourceLocale": { "type": "string", "nullable": true }, "createdAt": { "type": "string" } }, "required": [ "id", "object", "name", "slug", "aliasSlugs", "sourceLocale", "createdAt" ] }, "CreateSkillBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200 }, "slug": { "type": "string", "minLength": 1, "maxLength": 120, "pattern": "^[a-z0-9-]+$" }, "aliasSlugs": { "type": "array", "items": { "type": "string", "minLength": 1 }, "maxItems": 20 }, "sourceLocale": { "type": "string", "minLength": 2, "maxLength": 16 } }, "required": [ "name" ], "additionalProperties": false }, "UpdateSkillBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200 }, "slug": { "type": "string", "minLength": 1, "maxLength": 120, "pattern": "^[a-z0-9-]+$" }, "sourceLocale": { "type": "string", "minLength": 2, "maxLength": 16 } }, "additionalProperties": false }, "AddSkillAliasesBody": { "type": "object", "properties": { "aliases": { "type": "array", "items": { "type": "string", "minLength": 1 }, "minItems": 1, "maxItems": 20 } }, "required": [ "aliases" ], "additionalProperties": false }, "Transaction": { "type": "object", "properties": { "id": { "type": "string" }, "object": { "type": "string", "enum": [ "transaction" ] }, "kind": { "type": "string", "enum": [ "card_post", "invoice", "subscription" ] }, "status": { "type": "string", "enum": [ "paid", "open", "void", "uncollectible" ] }, "method": { "type": "string", "enum": [ "card", "invoice" ] }, "amountCents": { "type": "integer", "description": "Amount in currency minor units (cents for most currencies)." }, "currency": { "type": "string" }, "description": { "type": "string" }, "customerLabel": { "type": "string" }, "customerEmail": { "type": "string", "nullable": true }, "date": { "type": "string", "description": "ISO-8601 transaction date." }, "invoiceDueAt": { "type": "string", "nullable": true, "description": "ISO-8601 invoice due date, or null. Past-due is client-derived from this field." }, "hostedInvoiceUrl": { "type": "string", "nullable": true }, "receiptUrl": { "type": "string", "nullable": true }, "methodBrand": { "type": "string", "nullable": true }, "methodLast4": { "type": "string", "nullable": true }, "methodType": { "type": "string", "nullable": true }, "publishTiming": { "type": "string", "nullable": true, "enum": [ "on_issue", "on_payment" ] } }, "required": [ "id", "object", "kind", "status", "method", "amountCents", "currency", "description", "customerLabel", "customerEmail", "date", "invoiceDueAt", "hostedInvoiceUrl", "receiptUrl", "methodBrand", "methodLast4", "methodType", "publishTiming" ] }, "Usage": { "type": "object", "properties": { "object": { "type": "string", "enum": [ "usage" ], "description": "String representing the object's type. Objects of the same type share the same value." }, "capacities": { "type": "array", "items": { "$ref": "#/components/schemas/UsageCapacity" }, "description": "Typed product capacities for active jobs, confirmed subscribers, and team seats." } }, "required": [ "object", "capacities" ] }, "AnalyticsDateRange": { "type": "object", "properties": { "start": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "description": "UTC date-only YYYY-MM-DD." }, "end": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "description": "UTC date-only YYYY-MM-DD." } }, "required": [ "start", "end" ] }, "AnalyticsMetric": { "type": "object", "properties": { "key": { "type": "string", "enum": [ "sessions", "page_views", "average_session_duration", "job_apply_clicks", "impressions", "stripe_revenue", "adsense_revenue" ] }, "unit": { "type": "string", "enum": [ "count", "seconds", "currency" ] }, "currency": { "type": "string", "description": "ISO currency code in lowercase when unit is currency." }, "current": { "type": "object", "properties": { "total": { "type": "number" }, "change": { "$ref": "#/components/schemas/AnalyticsChange" }, "points": { "type": "array", "items": { "$ref": "#/components/schemas/AnalyticsTrendPoint" } } }, "required": [ "total", "change", "points" ] }, "previous": { "type": "object", "properties": { "total": { "type": "number" }, "points": { "type": "array", "items": { "$ref": "#/components/schemas/AnalyticsTrendPoint" } } }, "required": [ "total", "points" ] }, "dataAvailableThrough": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "description": "Latest available day for lagging providers (GSC/AdSense) when the window tail is incomplete." } }, "required": [ "key", "unit", "current", "previous" ] }, "AnalyticsTrafficDateRange": { "type": "object", "properties": { "start": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "description": "UTC date-only YYYY-MM-DD." }, "end": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "description": "UTC date-only YYYY-MM-DD." } }, "required": [ "start", "end" ] }, "AnalyticsTrafficPage": { "type": "object", "properties": { "pathname": { "type": "string" }, "visits": { "type": "number" }, "visitsChangePercentage": { "type": "number", "nullable": true } }, "required": [ "pathname", "visits", "visitsChangePercentage" ] }, "AnalyticsTrafficSource": { "type": "object", "properties": { "source": { "type": "string", "description": "Normalized referrer source (never a full URL)." }, "visits": { "type": "number" }, "visitsChangePercentage": { "type": "number", "nullable": true }, "applyClicks": { "type": "number" } }, "required": [ "source", "visits", "visitsChangePercentage", "applyClicks" ] }, "AnalyticsTrafficLocation": { "type": "object", "properties": { "countryCode": { "type": "string" }, "visits": { "type": "number" }, "visitsChangePercentage": { "type": "number", "nullable": true }, "applyClicks": { "type": "number" } }, "required": [ "countryCode", "visits", "visitsChangePercentage", "applyClicks" ] }, "AnalyticsTrafficDevice": { "type": "object", "properties": { "device": { "type": "string" }, "visits": { "type": "number" }, "visitsChangePercentage": { "type": "number", "nullable": true }, "applyClicks": { "type": "number" } }, "required": [ "device", "visits", "visitsChangePercentage", "applyClicks" ] }, "BackfillMatchCandidate": { "type": "object", "properties": { "index": { "type": "integer", "minimum": 0 }, "name": { "type": "string" }, "website": { "type": "string", "nullable": true } }, "required": [ "index", "name", "website" ] }, "BackfillBulkItemResult": { "type": "object", "properties": { "companyId": { "type": "string" }, "status": { "type": "string", "enum": [ "ok", "error" ] }, "error": { "type": "object", "properties": { "code": { "type": "string" }, "message": { "type": "string" } }, "required": [ "code", "message" ] } }, "required": [ "companyId", "status" ] }, "BillingHostedCheckoutFunding": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "hosted_checkout" ] } }, "required": [ "type" ] }, "OperationProgress": { "type": "object", "nullable": true, "properties": { "percent": { "type": "number", "description": "Progress as a percentage between 0 and 100, when the operation reports a percentage." }, "message": { "type": "string", "description": "Human-readable progress message, when available." }, "processed": { "type": "number", "description": "Number of items processed so far, when applicable." }, "total": { "type": "number", "description": "Total number of items to process, when known." } }, "description": "Snapshot of the operation's progress, or `null` if the operation does not report progress." }, "OperationErrorEnvelope": { "type": "object", "nullable": true, "properties": { "code": { "type": "string", "description": "Machine-readable error code." }, "message": { "type": "string", "description": "Human-readable error message." } }, "required": [ "code", "message" ], "description": "Error envelope, populated once the operation reaches `failed`. `null` otherwise." }, "CandidateProfile": { "type": "object", "properties": { "id": { "type": "string" }, "object": { "type": "string", "enum": [ "candidate_profile" ] }, "displayName": { "type": "string", "nullable": true }, "bio": { "type": "string", "nullable": true }, "avatarUrl": { "type": "string", "nullable": true }, "handle": { "type": "string", "nullable": true }, "headline": { "type": "string", "nullable": true }, "location": { "type": "string", "nullable": true }, "profileVisibility": { "type": "string", "enum": [ "hidden", "logged_in_only", "public" ] }, "jobSearchStatus": { "type": "string", "enum": [ "actively_looking", "open_to_offers", "not_looking" ] }, "jobSearchStatusVisibleTo": { "type": "string", "enum": [ "everyone", "employers_only" ] }, "openToRelocate": { "type": "boolean" } }, "required": [ "id", "object", "displayName", "bio", "avatarUrl", "handle", "headline", "location", "profileVisibility", "jobSearchStatus", "jobSearchStatusVisibleTo", "openToRelocate" ] }, "CandidateResumeFile": { "type": "object", "nullable": true, "properties": { "downloadUrl": { "type": "string", "description": "Stable, permission-protected Cavuno API path for downloading the candidate resume." }, "contentType": { "type": "string", "description": "MIME type of the stored resume file." }, "sizeBytes": { "type": "number", "description": "Size of the resume file in bytes." } }, "required": [ "downloadUrl", "contentType", "sizeBytes" ], "description": "Protected download path and metadata for the uploaded resume, or `null` when no resume is on file (or the storage blob is missing)." }, "ResourceLinks": { "type": "object", "properties": { "public": { "type": "string", "format": "uri", "description": "Canonical public URL for this resource on the board. Honours the configured custom domain when present, otherwise uses the board subdomain." }, "admin": { "type": "string", "format": "uri", "description": "URL inside the Cavuno app where the authenticated owner can manage this resource." } }, "required": [ "public", "admin" ] }, "DomainVerificationInstructions": { "type": "object", "properties": { "method": { "type": "string", "enum": [ "txt" ] }, "name": { "type": "string" }, "expectedValue": { "type": "string", "nullable": true } }, "required": [ "method", "name", "expectedValue" ] }, "EmployerCompany": { "type": "object", "properties": { "id": { "type": "string" }, "object": { "type": "string", "enum": [ "employer_company" ] }, "name": { "type": "string" }, "slug": { "type": "string" }, "website": { "type": "string", "nullable": true }, "description": { "type": "string", "nullable": true }, "summary": { "type": "string", "nullable": true }, "xUrl": { "type": "string", "nullable": true }, "linkedinUrl": { "type": "string", "nullable": true }, "facebookUrl": { "type": "string", "nullable": true }, "logoUrl": { "type": "string", "nullable": true } }, "required": [ "id", "object", "name", "slug", "website", "description", "summary", "xUrl", "linkedinUrl", "facebookUrl", "logoUrl" ] }, "EmployerPendingClaim": { "type": "object", "properties": { "membershipId": { "type": "string" }, "companyId": { "type": "string" }, "companyName": { "type": "string" }, "companyWebsiteDomain": { "type": "string", "nullable": true }, "workEmail": { "type": "string", "nullable": true }, "workEmailVerifiedAt": { "type": "string", "nullable": true } }, "required": [ "membershipId", "companyId", "companyName", "companyWebsiteDomain", "workEmail", "workEmailVerifiedAt" ] }, "ImportBatchError": { "type": "object", "properties": { "rowIndex": { "type": "number" }, "code": { "type": "string" }, "message": { "type": "string" } }, "required": [ "rowIndex", "code", "message" ] }, "AdminOnlyResourceLinks": { "type": "object", "properties": { "admin": { "type": "string", "format": "uri", "description": "URL inside the Cavuno app where the authenticated owner can manage this resource." } }, "required": [ "admin" ], "description": "Links related to this resource. List responses carry the operator URL; detail responses may also carry the public URL." }, "JobOfficeLocationInput": { "anyOf": [ { "type": "object", "properties": { "locality": { "type": "string", "minLength": 1, "description": "Neighborhood or sub-locality." }, "city": { "type": "string", "minLength": 1, "description": "City." }, "region": { "type": "string", "minLength": 1, "description": "Region, state, or province." }, "country": { "type": "string", "minLength": 1, "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`)." } }, "required": [ "city", "country" ], "additionalProperties": false }, { "type": "object", "properties": { "query": { "type": "string", "minLength": 1, "maxLength": 500, "description": "Free-form location string (e.g. `\"Berlin, Germany\"`, `\"Mountain View, California, USA\"`). Mapbox parses + ranks candidates server-side; rejects on low confidence." } }, "required": [ "query" ], "additionalProperties": false } ] }, "InlineCompanyInput": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 120, "description": "The company's display name." }, "website": { "type": "string", "maxLength": 200, "description": "Public company website URL. Used to resolve to an existing company by domain before falling back to creation." }, "summary": { "type": "string", "maxLength": 280, "description": "One-line summary of the company. Up to 280 characters." }, "matchByName": { "type": "boolean", "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." }, "createIfMissing": { "type": "boolean", "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." } }, "required": [ "name" ], "additionalProperties": false, "description": "An inline company payload, resolved via `find-or-create` before the job is created. Provide either `company` or `companyId`, not both." }, "JobCompany": { "type": "object", "nullable": true, "properties": { "id": { "type": "string", "description": "Unique identifier for the company." }, "name": { "type": "string", "nullable": true, "description": "Display name of the company, or `null` if not yet set." }, "slug": { "type": "string", "nullable": true, "description": "URL slug of the company, or `null` if not yet set." }, "logoUrl": { "type": "string", "nullable": true, "description": "URL of the company logo, or `null` if no logo is set." }, "website": { "type": "string", "nullable": true, "description": "Company website URL, or `null` if no website is set." } }, "required": [ "id", "name", "slug", "logoUrl", "website" ], "description": "Embedded company resource for the job, or `null` if no company is attached." }, "JobOfficeLocation": { "type": "object", "properties": { "countryCode": { "type": "string", "nullable": true, "description": "ISO 3166-1 alpha-2 country code, or `null` if the location was not resolved." }, "country": { "type": "string", "nullable": true, "description": "Full country name, or `null` if the location was not resolved." }, "locality": { "type": "string", "nullable": true, "description": "Neighborhood or sub-locality, or `null` if not resolved." }, "city": { "type": "string", "nullable": true, "description": "City, or `null` if not resolved." }, "region": { "type": "string", "nullable": true, "description": "Region, state, or province name, or `null` if not resolved." }, "regionCode": { "type": "string", "nullable": true, "description": "Region or state code (e.g. `CA` for California), or `null` if not resolved." }, "postalCode": { "type": "string", "nullable": true, "description": "Postal or ZIP code, or `null` if not resolved." }, "displayName": { "type": "string", "nullable": true, "description": "Pre-formatted display name for the location, or `null` if not resolved." } }, "required": [ "countryCode", "country", "locality", "city", "region", "regionCode", "postalCode", "displayName" ] }, "CandidatePaywallOffer": { "type": "object", "properties": { "key": { "type": "string", "enum": [ "daily", "weekly", "monthly", "quarterly", "yearly", "lifetime" ] }, "kind": { "type": "string", "enum": [ "recurring", "lifetime" ] }, "enabled": { "type": "boolean" }, "amountCents": { "type": "integer", "minimum": 0 }, "label": { "type": "string", "maxLength": 60 }, "billingLabel": { "type": "string", "maxLength": 60 }, "isDefault": { "type": "boolean" }, "displayOrder": { "type": "integer", "minimum": 0 }, "intervalUnit": { "type": "string", "nullable": true, "enum": [ "day", "week", "month", "year" ] }, "intervalCount": { "type": "integer", "nullable": true, "minimum": 0, "exclusiveMinimum": true } }, "required": [ "key", "kind", "enabled", "amountCents", "label", "billingLabel", "isDefault", "displayOrder", "intervalUnit", "intervalCount" ] }, "PlanFeature": { "type": "object", "properties": { "key": { "type": "string", "enum": [ "jobs.max_active", "jobs.duration_days", "jobs.featured_slots", "jobs.feature_selection_mode", "talent.profile_unlocks", "talent.messages_sent" ], "description": "Stable Cavuno plan capability key." }, "name": { "type": "string", "nullable": true }, "value": { "type": "string", "nullable": true } }, "required": [ "key", "name", "value" ] }, "OperatorSettingsConfig": { "type": "object", "properties": { "passwordProtectionEnabled": { "type": "boolean" }, "jobAlertsEnabled": { "type": "boolean" }, "candidatesEnabled": { "type": "boolean" }, "employersEnabled": { "type": "boolean" }, "blogEnabled": { "type": "boolean" }, "impressumEnabled": { "type": "boolean" }, "requireApprovalFreeJobs": { "type": "boolean" }, "requireApprovalAggregatedJobs": { "type": "boolean" }, "registrationWallEnabled": { "type": "boolean" }, "nativeApplicationsEnabled": { "type": "boolean" }, "applicantMessagingEnabled": { "type": "boolean" }, "requireCookieConsent": { "type": "boolean" }, "showCavunoBranding": { "type": "boolean" }, "cookieBannerTitle": { "type": "string" }, "cookieBannerDescription": { "type": "string" }, "cookieBannerRejectLabel": { "type": "string" }, "cookieBannerAcceptLabel": { "type": "string" }, "cookieBannerManageLabel": { "type": "string" }, "talentNavLabel": { "type": "string" }, "contactEmail": { "type": "string", "nullable": true }, "companyLegalName": { "type": "string", "nullable": true }, "companyAddress": { "type": "string", "nullable": true }, "companyWebsiteUrl": { "type": "string", "nullable": true }, "companyXHandle": { "type": "string", "nullable": true }, "companyFacebookUrl": { "type": "string", "nullable": true }, "companyLinkedinUrl": { "type": "string", "nullable": true }, "passwordProtectionMessage": { "type": "string", "nullable": true }, "defaultJobDurationDays": { "type": "integer", "minimum": 0, "exclusiveMinimum": true }, "talentDirectoryVisibility": { "type": "string", "enum": [ "off", "public", "employers_only" ] } }, "additionalProperties": false }, "SettingsAdsenseSlot": { "type": "object", "properties": { "enabled": { "type": "boolean", "description": "Whether this placement is rendered." }, "slotId": { "anyOf": [ { "type": "string", "pattern": "^[0-9]{10}$" }, { "type": "string", "enum": [ "" ] }, { "nullable": true }, { "nullable": true } ], "description": "Ten-digit AdSense slot ID. Pass an empty string or `null` to clear." }, "layout": { "anyOf": [ { "type": "string", "enum": [ "auto", "in-article", "in-feed", "fluid" ] }, { "type": "string", "enum": [ "" ] }, { "nullable": true }, { "nullable": true } ], "description": "AdSense layout type for the placement." }, "format": { "anyOf": [ { "type": "string", "enum": [ "auto", "horizontal", "vertical", "rectangle", "responsive" ] }, { "type": "string", "enum": [ "" ] }, { "nullable": true }, { "nullable": true } ], "description": "AdSense ad format." }, "style": { "anyOf": [ { "type": "string", "enum": [ "default", "light", "dark", "contrast" ] }, { "type": "string", "enum": [ "" ] }, { "nullable": true }, { "nullable": true } ], "description": "Visual style override for the placement." }, "frequency": { "anyOf": [ { "type": "integer", "minimum": 1, "maximum": 50 }, { "nullable": true }, { "nullable": true } ], "description": "How often the placement is shown (e.g. once every N items)." } }, "required": [ "enabled", "slotId" ] }, "CustomFieldDefinition": { "type": "object", "properties": { "key": { "type": "string", "description": "Immutable per-board slug used as the key in a job’s `customFieldValues`." }, "label": { "type": "string", "description": "Authoring-default label; the localized public string lives in the board template." }, "type": { "type": "string", "enum": [ "short_text", "long_text", "single_select", "multi_select", "boolean", "number" ], "description": "Field type, which dictates the value: `short_text`/`long_text` → string; `single_select` → one option key; `multi_select` → array of option keys; `boolean` → boolean; `number` → number." }, "options": { "type": "array", "items": { "$ref": "#/components/schemas/CustomFieldOption" }, "description": "Present only for `single_select`/`multi_select`. A stored value is one (or, for multi, several) of these option `key`s — never a label." }, "required": { "type": "boolean", "description": "When true, the value cannot be cleared or left empty on a write (rejected with `custom_field_required`)." }, "min": { "type": "number", "description": "Inclusive minimum for `number` fields, when set." }, "max": { "type": "number", "description": "Inclusive maximum for `number` fields, when set." } }, "required": [ "key", "label", "type", "required" ] }, "UsageCapacity": { "type": "object", "properties": { "key": { "type": "string", "enum": [ "active_jobs", "confirmed_subscribers", "team_seats" ], "description": "Stable capacity key matching the dashboard: active_jobs, confirmed_subscribers, or team_seats." }, "used": { "type": "integer", "minimum": 0, "description": "Current usage for this capacity. Never negative." }, "limit": { "type": "integer", "nullable": true, "minimum": 0, "description": "Effective plan or override cap. Null when the capacity is unlimited." }, "remaining": { "type": "integer", "nullable": true, "minimum": 0, "description": "Slots remaining before the limit. Null when unlimited; never negative when finite." } }, "required": [ "key", "used", "limit", "remaining" ] }, "AnalyticsChange": { "type": "object", "properties": { "absolute": { "type": "number" }, "percentage": { "type": "number", "nullable": true, "description": "Null when both periods are zero (undefined percent change)." } }, "required": [ "absolute", "percentage" ] }, "AnalyticsTrendPoint": { "type": "object", "properties": { "date": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "description": "UTC date-only YYYY-MM-DD." }, "value": { "type": "number", "nullable": true, "description": "Metric value for the day, or null when a lagging provider has not reported yet." } }, "required": [ "date", "value" ] }, "CustomFieldOption": { "type": "object", "properties": { "key": { "type": "string", "description": "Stable option key — the value stored on a job, not the label." }, "label": { "type": "string", "description": "Display label (authoring default; localized per board in the template)." } }, "required": [ "key", "label" ] } } } }