{"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\n### Plan upgrade hints\n\nWhen an Operator API request is refused because of the board's Cavuno plan, the error also carries an `upgrade` object. It names the capability that blocked the request, the cheapest self-serve plan that unlocks it (when that can be told), and the hosted billing endpoints that start the upgrade:\n\n```json\n{\n  \"error\": {\n    \"code\": \"settings_plan_required_for_branding_removal\",\n    \"message\": \"Removing Cavuno branding requires a plan that includes branding removal.\",\n    \"requestId\": \"req_...\",\n    \"upgrade\": {\n      \"capability\": \"canRemoveBranding\",\n      \"requiredPlan\": \"basic\",\n      \"checkout\": { \"method\": \"POST\", \"path\": \"/v1/billing/checkout\" },\n      \"changePlan\": { \"method\": \"POST\", \"path\": \"/v1/billing/upgrade\" }\n    }\n  }\n}\n```\n\nCall `GET /v1/billing/subscription` first. With no active subscription, use `checkout`; with one, use `changePlan`. Send `{ \"planKey\": \"<requiredPlan>\" }` and give the returned `url` to a person: both endpoints return a hosted page where a person confirms the purchase. Nothing is charged until they do. Each `path` is relative to the API origin (`https://api.cavuno.com`), like `Location` headers and list `url` fields, so do not join it to a base URL that already ends in `/v1`. Both endpoints need a key with `billing.manage`; a key without it should hand the person the dashboard's billing page instead. Board API errors never carry this field.\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\n## Reporting problems\n\nAI agents can report anything that got in the way of a task: a missing capability, unclear documentation, a surprising response, an unhelpful error, a bug or slow performance. `POST /v1/feedback` accepts [Agent Feedback Protocol v0.1](https://trybackloop.com/spec/) reports, with or without an API key, and API error responses link to it in a `Link: <https://api.cavuno.com/v1/feedback>; rel=\"agent-feedback\"` header. The discovery document is at `https://api.cavuno.com/.well-known/agent-feedback`.\n\n```bash\ncurl https://api.cavuno.com/v1/feedback \\\n  -X POST \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"type\": \"missing_capability\", \"goal\": \"What you were trying to do\", \"message\": \"What got in the way\", \"agent\": { \"name\": \"my-agent\", \"model\": \"model-name\" } }'\n```\n\n`type`, `goal` and `message` are required. Each account or visitor can send 20 reports every 5 minutes. Never include credentials or personal data. Send the report, then continue with your task.\n","contact":{"name":"Cavuno","url":"https://cavuno.com"}},"externalDocs":{"description":"Cavuno API reference","url":"https://cavuno.com/docs/api"},"servers":[{"url":"https://api.cavuno.com/v1","description":"Production"}],"security":[{"bearerAuth":[]}],"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 and email sender domains, and manage the development origins where sign-in may complete while you test a self-hosted frontend."},{"name":"Webhooks","description":"Configure Board-owned outbound webhook endpoints, inspect delivery history, and replay completed deliveries."},{"name":"Marketing permissions","description":"Read marketing-email consent decisions off the board user records, and withdraw on request."},{"name":"Redirects","description":"Create, list, update, and delete board redirect rules."},{"name":"Agent feedback","description":"Report a problem an AI agent hit with the API, CLI, MCP server or SDK (Agent Feedback Protocol v0.1)."},{"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":"Page content","description":"Intro copy on category and location pages: retrieve, set, and delete."},{"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":"Job feeds","description":"Recurring XML job feeds pulled from a URL on a schedule: connect, map fields, re-detect, and track runs."},{"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_<keyId>_<secret>","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":{"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."},"upgrade":{"$ref":"#/components/schemas/PlanUpgradeHint"}},"required":["code","message","requestId"]}},"required":["error"],"description":"The error envelope returned by every non-2xx response."},"PlanUpgradeHint":{"type":"object","properties":{"capability":{"type":"string","enum":["activeJobsLimit","teamSeatLimit","canBePublic","canRemoveBranding","apiAccess"],"description":"The plan capability that blocked the request, named as in `GET /v1/billing/subscription` `capabilities`."},"requiredPlan":{"type":"string","enum":["starter","basic","grow","advanced","scale"],"description":"The cheapest self-serve plan that unlocks the action. Pass it as `planKey`. Omitted when it cannot be told without more information; read `GET /v1/billing/subscription` and pick a higher plan."},"checkout":{"type":"object","properties":{"method":{"type":"string","enum":["POST"]},"path":{"type":"string","enum":["/v1/billing/checkout"]}},"required":["method","path"],"description":"Starts a hosted checkout when the board has no active subscription (for example during a trial)."},"changePlan":{"type":"object","properties":{"method":{"type":"string","enum":["POST"]},"path":{"type":"string","enum":["/v1/billing/upgrade"]}},"required":["method","path"],"description":"Starts a hosted plan change when the board already has an active subscription."}},"required":["capability","checkout","changePlan"],"description":"Present only on Operator API errors caused by the board's Cavuno plan. Read `GET /v1/billing/subscription` to choose between `checkout` and `changePlan`, call it with `{ \"planKey\": requiredPlan }`, and give the returned `url` to a person to confirm. Each `path` is relative to the API origin, not to a `/v1` base URL. Both endpoints need `billing.manage`. Board API errors never include it."},"WebhookEventEnvelope":{"type":"object","properties":{"id":{"type":"string","description":"Stable public event id (evt_…)."},"object":{"type":"string","enum":["event"]},"type":{"type":"string","description":"Dot-delimited event type (e.g. job.created)."},"schema_version":{"type":"string","enum":["1"]},"occurred_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"board_id":{"type":"string","description":"Board account id that owns the event."},"data":{"type":"object","properties":{"object":{"type":"object","additionalProperties":{"nullable":true},"description":"Allowlisted resource snapshot or tombstone."},"changed_fields":{"type":"array","items":{"type":"string"},"description":"Closed vocabulary of fields that changed; empty for create/delete."}},"required":["object","changed_fields"]}},"required":["id","object","type","schema_version","occurred_at","board_id","data"],"description":"Common outbound webhook event envelope.","example":{"id":"evt_01EXAMPLEJOBCREATED","object":"event","type":"job.created","schema_version":"1","occurred_at":"2026-07-24T12:00:00Z","board_id":"acc_01EXAMPLEBOARD","data":{"object":{"id":"jobs_01EXAMPLEJOB","object":"job","slug":"senior-engineer","title":"Senior Engineer","status":"published","company_id":"companies_01EXAMPLE","company_name":"Acme","location":"Remote","description":"<p>Build the next generation of robotics platforms.</p>","url":"https://example-board.cavuno.com/companies/acme/jobs/senior-engineer","employment_type":"full_time","workplace_type":"remote","published_at":"2026-07-24T12:00:00Z","expires_at":"2026-08-23T12:00:00Z","updated_at":"2026-07-24T12:00:00Z","revision":1},"changed_fields":[]}}},"WebhookJobSnapshot":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["job"]},"slug":{"type":"string","nullable":true},"title":{"type":"string"},"status":{"type":"string"},"company_id":{"type":"string","nullable":true},"company_name":{"type":"string","nullable":true},"location":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"url":{"type":"string","nullable":true,"format":"uri"},"employment_type":{"type":"string","nullable":true},"workplace_type":{"type":"string","nullable":true},"published_at":{"type":"string","nullable":true,"description":"ISO-8601 UTC timestamp with second precision (…Z)."},"expires_at":{"type":"string","nullable":true,"description":"ISO-8601 UTC timestamp with second precision (…Z)."},"updated_at":{"type":"string","nullable":true,"description":"ISO-8601 UTC timestamp with second precision (…Z)."},"revision":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["id","object","slug","title","status","company_id","company_name","location","description","url","employment_type","workplace_type","published_at","expires_at","updated_at","revision"],"description":"V1 Job snapshot on job.created / job.updated. Explicit allowlist — never a raw row. Includes HTML description for automation consumers (Zapier, n8n).","example":{"id":"jobs_01EXAMPLEJOB","object":"job","slug":"senior-engineer","title":"Senior Engineer","status":"published","company_id":"companies_01EXAMPLE","company_name":"Acme","location":"Remote","description":"<p>Build the next generation of robotics platforms.</p>","url":"https://example-board.cavuno.com/companies/acme/jobs/senior-engineer","employment_type":"full_time","workplace_type":"remote","published_at":"2026-07-24T12:00:00Z","expires_at":"2026-08-23T12:00:00Z","updated_at":"2026-07-24T12:00:00Z","revision":1}},"WebhookJobTombstone":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["job"]},"revision":{"type":"integer","minimum":0,"exclusiveMinimum":true},"deleted":{"type":"boolean","enum":[true]},"deleted_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"slug":{"type":"string","nullable":true},"company_id":{"type":"string","nullable":true}},"required":["id","object","revision","deleted","deleted_at","slug","company_id"],"description":"V1 Job delete tombstone. Minimum identity to drop a downstream copy without re-fetching.","example":{"id":"jobs_01EXAMPLEJOB","object":"job","revision":3,"deleted":true,"deleted_at":"2026-07-24T14:00:00Z","slug":"senior-engineer","company_id":"companies_01EXAMPLE"}},"WebhookJobChangedField":{"type":"string","enum":["slug","title","status","company_id","company_name","location","description","url","employment_type","workplace_type","published_at","expires_at"],"description":"A single closed Job changed_fields vocabulary member.","example":"title"},"WebhookJobCreatedEvent":{"type":"object","properties":{"id":{"type":"string","description":"Stable public event id (evt_…)."},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["job.created"]},"schema_version":{"type":"string","enum":["1"]},"occurred_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"board_id":{"type":"string","description":"Board account id that owns the event."},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["job"]},"slug":{"type":"string","nullable":true},"title":{"type":"string"},"status":{"type":"string"},"company_id":{"type":"string","nullable":true},"company_name":{"type":"string","nullable":true},"location":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"url":{"type":"string","nullable":true,"format":"uri"},"employment_type":{"type":"string","nullable":true},"workplace_type":{"type":"string","nullable":true},"published_at":{"type":"string","nullable":true,"description":"ISO-8601 UTC timestamp with second precision (…Z)."},"expires_at":{"type":"string","nullable":true,"description":"ISO-8601 UTC timestamp with second precision (…Z)."},"updated_at":{"type":"string","nullable":true,"description":"ISO-8601 UTC timestamp with second precision (…Z)."},"revision":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["id","object","slug","title","status","company_id","company_name","location","description","url","employment_type","workplace_type","published_at","expires_at","updated_at","revision"],"description":"V1 Job snapshot on job.created / job.updated. Explicit allowlist — never a raw row. Includes HTML description for automation consumers (Zapier, n8n)."},"changed_fields":{"type":"array","items":{"type":"string"},"maxItems":0,"description":"Empty for create/delete events."}},"required":["object","changed_fields"]}},"required":["id","object","type","schema_version","occurred_at","board_id","data"],"example":{"id":"evt_01EXAMPLEJOBCREATED","object":"event","type":"job.created","schema_version":"1","occurred_at":"2026-07-24T12:00:00Z","board_id":"acc_01EXAMPLEBOARD","data":{"object":{"id":"jobs_01EXAMPLEJOB","object":"job","slug":"senior-engineer","title":"Senior Engineer","status":"published","company_id":"companies_01EXAMPLE","company_name":"Acme","location":"Remote","description":"<p>Build the next generation of robotics platforms.</p>","url":"https://example-board.cavuno.com/companies/acme/jobs/senior-engineer","employment_type":"full_time","workplace_type":"remote","published_at":"2026-07-24T12:00:00Z","expires_at":"2026-08-23T12:00:00Z","updated_at":"2026-07-24T12:00:00Z","revision":1},"changed_fields":[]}}},"WebhookJobUpdatedEvent":{"type":"object","properties":{"id":{"type":"string","description":"Stable public event id (evt_…)."},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["job.updated"]},"schema_version":{"type":"string","enum":["1"]},"occurred_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"board_id":{"type":"string","description":"Board account id that owns the event."},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["job"]},"slug":{"type":"string","nullable":true},"title":{"type":"string"},"status":{"type":"string"},"company_id":{"type":"string","nullable":true},"company_name":{"type":"string","nullable":true},"location":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"url":{"type":"string","nullable":true,"format":"uri"},"employment_type":{"type":"string","nullable":true},"workplace_type":{"type":"string","nullable":true},"published_at":{"type":"string","nullable":true,"description":"ISO-8601 UTC timestamp with second precision (…Z)."},"expires_at":{"type":"string","nullable":true,"description":"ISO-8601 UTC timestamp with second precision (…Z)."},"updated_at":{"type":"string","nullable":true,"description":"ISO-8601 UTC timestamp with second precision (…Z)."},"revision":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["id","object","slug","title","status","company_id","company_name","location","description","url","employment_type","workplace_type","published_at","expires_at","updated_at","revision"],"description":"V1 Job snapshot on job.created / job.updated. Explicit allowlist — never a raw row. Includes HTML description for automation consumers (Zapier, n8n)."},"changed_fields":{"type":"array","items":{"type":"string","enum":["slug","title","status","company_id","company_name","location","description","url","employment_type","workplace_type","published_at","expires_at"]},"description":"Closed Job changed_fields vocabulary for job.updated."}},"required":["object","changed_fields"]}},"required":["id","object","type","schema_version","occurred_at","board_id","data"],"example":{"id":"evt_01EXAMPLEJOBUPDATED","object":"event","type":"job.updated","schema_version":"1","occurred_at":"2026-07-24T13:00:00Z","board_id":"acc_01EXAMPLEBOARD","data":{"object":{"id":"jobs_01EXAMPLEJOB","object":"job","slug":"senior-engineer","title":"Staff Engineer","status":"published","company_id":"companies_01EXAMPLE","company_name":"Acme","location":"Remote","description":"<p>Build the next generation of robotics platforms.</p>","url":"https://example-board.cavuno.com/companies/acme/jobs/senior-engineer","employment_type":"full_time","workplace_type":"remote","published_at":"2026-07-24T12:00:00Z","expires_at":"2026-08-23T12:00:00Z","updated_at":"2026-07-24T13:00:00Z","revision":2},"changed_fields":["title"]}}},"WebhookJobDeletedEvent":{"type":"object","properties":{"id":{"type":"string","description":"Stable public event id (evt_…)."},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["job.deleted"]},"schema_version":{"type":"string","enum":["1"]},"occurred_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"board_id":{"type":"string","description":"Board account id that owns the event."},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["job"]},"revision":{"type":"integer","minimum":0,"exclusiveMinimum":true},"deleted":{"type":"boolean","enum":[true]},"deleted_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"slug":{"type":"string","nullable":true},"company_id":{"type":"string","nullable":true}},"required":["id","object","revision","deleted","deleted_at","slug","company_id"],"description":"V1 Job delete tombstone. Minimum identity to drop a downstream copy without re-fetching."},"changed_fields":{"type":"array","items":{"type":"string"},"maxItems":0,"description":"Empty for create/delete events."}},"required":["object","changed_fields"]}},"required":["id","object","type","schema_version","occurred_at","board_id","data"],"example":{"id":"evt_01EXAMPLEJOBDELETED","object":"event","type":"job.deleted","schema_version":"1","occurred_at":"2026-07-24T14:00:00Z","board_id":"acc_01EXAMPLEBOARD","data":{"object":{"id":"jobs_01EXAMPLEJOB","object":"job","revision":3,"deleted":true,"deleted_at":"2026-07-24T14:00:00Z","slug":"senior-engineer","company_id":"companies_01EXAMPLE"},"changed_fields":[]}}},"WebhookCompanySnapshot":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["company"]},"slug":{"type":"string"},"name":{"type":"string"},"website":{"type":"string","nullable":true},"logo_url":{"type":"string","nullable":true},"url":{"type":"string","nullable":true,"format":"uri"},"updated_at":{"type":"string","nullable":true,"description":"ISO-8601 UTC timestamp with second precision (…Z)."},"revision":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["id","object","slug","name","website","logo_url","url","updated_at","revision"],"description":"V1 Company snapshot. Explicit allowlist; includes public board URL for automation.","example":{"id":"companies_01EXAMPLE","object":"company","slug":"acme","name":"Acme","website":"https://acme.example","logo_url":null,"url":"https://example-board.cavuno.com/companies/acme","updated_at":"2026-07-24T12:00:00Z","revision":1}},"WebhookCompanyTombstone":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["company"]},"revision":{"type":"integer","minimum":0,"exclusiveMinimum":true},"deleted":{"type":"boolean","enum":[true]},"deleted_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"slug":{"type":"string"}},"required":["id","object","revision","deleted","deleted_at","slug"],"description":"V1 Company deletion tombstone.","example":{"id":"companies_01EXAMPLE","object":"company","revision":3,"deleted":true,"deleted_at":"2026-07-24T14:00:00Z","slug":"acme"}},"WebhookCompanyChangedField":{"type":"string","enum":["slug","name","website","logo_url","url"],"example":"name"},"WebhookCompanyCreatedEvent":{"type":"object","properties":{"id":{"type":"string","description":"Stable public event id (evt_…)."},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["company.created"]},"schema_version":{"type":"string","enum":["1"]},"occurred_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"board_id":{"type":"string","description":"Board account id that owns the event."},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["company"]},"slug":{"type":"string"},"name":{"type":"string"},"website":{"type":"string","nullable":true},"logo_url":{"type":"string","nullable":true},"url":{"type":"string","nullable":true,"format":"uri"},"updated_at":{"type":"string","nullable":true,"description":"ISO-8601 UTC timestamp with second precision (…Z)."},"revision":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["id","object","slug","name","website","logo_url","url","updated_at","revision"],"description":"V1 Company snapshot. Explicit allowlist; includes public board URL for automation."},"changed_fields":{"type":"array","items":{"type":"string"},"maxItems":0,"description":"Empty for create/delete events."}},"required":["object","changed_fields"]}},"required":["id","object","type","schema_version","occurred_at","board_id","data"],"example":{"id":"evt_01EXAMPLECOMPANYCREATED","object":"event","type":"company.created","schema_version":"1","occurred_at":"2026-07-24T12:00:00Z","board_id":"acc_01EXAMPLEBOARD","data":{"object":{"id":"companies_01EXAMPLE","object":"company","slug":"acme","name":"Acme","website":"https://acme.example","logo_url":null,"url":"https://example-board.cavuno.com/companies/acme","updated_at":"2026-07-24T12:00:00Z","revision":1},"changed_fields":[]}}},"WebhookCompanyUpdatedEvent":{"type":"object","properties":{"id":{"type":"string","description":"Stable public event id (evt_…)."},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["company.updated"]},"schema_version":{"type":"string","enum":["1"]},"occurred_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"board_id":{"type":"string","description":"Board account id that owns the event."},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["company"]},"slug":{"type":"string"},"name":{"type":"string"},"website":{"type":"string","nullable":true},"logo_url":{"type":"string","nullable":true},"url":{"type":"string","nullable":true,"format":"uri"},"updated_at":{"type":"string","nullable":true,"description":"ISO-8601 UTC timestamp with second precision (…Z)."},"revision":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["id","object","slug","name","website","logo_url","url","updated_at","revision"],"description":"V1 Company snapshot. Explicit allowlist; includes public board URL for automation."},"changed_fields":{"type":"array","items":{"type":"string","enum":["slug","name","website","logo_url","url"]},"description":"Closed Company changed_fields vocabulary for company.updated."}},"required":["object","changed_fields"]}},"required":["id","object","type","schema_version","occurred_at","board_id","data"],"example":{"id":"evt_01EXAMPLECOMPANYUPDATED","object":"event","type":"company.updated","schema_version":"1","occurred_at":"2026-07-24T13:00:00Z","board_id":"acc_01EXAMPLEBOARD","data":{"object":{"id":"companies_01EXAMPLE","object":"company","slug":"acme","name":"Acme Corporation","website":"https://acme.example","logo_url":null,"url":"https://example-board.cavuno.com/companies/acme","updated_at":"2026-07-24T13:00:00Z","revision":2},"changed_fields":["name"]}}},"WebhookCompanyDeletedEvent":{"type":"object","properties":{"id":{"type":"string","description":"Stable public event id (evt_…)."},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["company.deleted"]},"schema_version":{"type":"string","enum":["1"]},"occurred_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"board_id":{"type":"string","description":"Board account id that owns the event."},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["company"]},"revision":{"type":"integer","minimum":0,"exclusiveMinimum":true},"deleted":{"type":"boolean","enum":[true]},"deleted_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"slug":{"type":"string"}},"required":["id","object","revision","deleted","deleted_at","slug"],"description":"V1 Company deletion tombstone."},"changed_fields":{"type":"array","items":{"type":"string"},"maxItems":0,"description":"Empty for create/delete events."}},"required":["object","changed_fields"]}},"required":["id","object","type","schema_version","occurred_at","board_id","data"],"example":{"id":"evt_01EXAMPLECOMPANYDELETED","object":"event","type":"company.deleted","schema_version":"1","occurred_at":"2026-07-24T14:00:00Z","board_id":"acc_01EXAMPLEBOARD","data":{"object":{"id":"companies_01EXAMPLE","object":"company","revision":3,"deleted":true,"deleted_at":"2026-07-24T14:00:00Z","slug":"acme"},"changed_fields":[]}}},"WebhookCandidateSnapshot":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["candidate"]},"email":{"type":"string"},"display_name":{"type":"string","nullable":true},"url":{"type":"string","nullable":true,"format":"uri"},"created_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"updated_at":{"type":"string","nullable":true,"description":"ISO-8601 UTC timestamp with second precision (…Z)."},"revision":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["id","object","email","display_name","url","created_at","updated_at","revision"],"description":"V1 Candidate snapshot. Explicit identity allowlist plus public talent profile URL when handle exists; never resumes, applications, or marketing permission.","example":{"id":"boardUsers_01EXAMPLE","object":"candidate","email":"candidate@example.test","display_name":"Example Candidate","url":"https://example-board.cavuno.com/p/example-candidate","created_at":"2026-08-03T12:00:00Z","updated_at":"2026-08-03T12:00:00Z","revision":1}},"WebhookCandidateTombstone":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["candidate"]},"revision":{"type":"integer","minimum":0,"exclusiveMinimum":true},"deleted":{"type":"boolean","enum":[true]},"deleted_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"email":{"type":"string"}},"required":["id","object","revision","deleted","deleted_at","email"],"description":"V1 Candidate permanent-erasure tombstone.","example":{"id":"boardUsers_01EXAMPLE","object":"candidate","revision":3,"deleted":true,"deleted_at":"2026-08-03T14:00:00Z","email":"candidate@example.test"}},"WebhookCandidateChangedField":{"type":"string","enum":["email","display_name","url"],"example":"display_name"},"WebhookCandidateCreatedEvent":{"type":"object","properties":{"id":{"type":"string","description":"Stable public event id (evt_…)."},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["candidate.created"]},"schema_version":{"type":"string","enum":["1"]},"occurred_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"board_id":{"type":"string","description":"Board account id that owns the event."},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["candidate"]},"email":{"type":"string"},"display_name":{"type":"string","nullable":true},"url":{"type":"string","nullable":true,"format":"uri"},"created_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"updated_at":{"type":"string","nullable":true,"description":"ISO-8601 UTC timestamp with second precision (…Z)."},"revision":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["id","object","email","display_name","url","created_at","updated_at","revision"],"description":"V1 Candidate snapshot. Explicit identity allowlist plus public talent profile URL when handle exists; never resumes, applications, or marketing permission."},"changed_fields":{"type":"array","items":{"type":"string"},"maxItems":0,"description":"Empty for create/delete events."}},"required":["object","changed_fields"]}},"required":["id","object","type","schema_version","occurred_at","board_id","data"],"example":{"id":"evt_01EXAMPLECANDIDATECREATED","object":"event","type":"candidate.created","schema_version":"1","occurred_at":"2026-08-03T12:00:00Z","board_id":"acc_01EXAMPLEBOARD","data":{"object":{"id":"boardUsers_01EXAMPLE","object":"candidate","email":"candidate@example.test","display_name":"Example Candidate","url":"https://example-board.cavuno.com/p/example-candidate","created_at":"2026-08-03T12:00:00Z","updated_at":"2026-08-03T12:00:00Z","revision":1},"changed_fields":[]}}},"WebhookCandidateUpdatedEvent":{"type":"object","properties":{"id":{"type":"string","description":"Stable public event id (evt_…)."},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["candidate.updated"]},"schema_version":{"type":"string","enum":["1"]},"occurred_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"board_id":{"type":"string","description":"Board account id that owns the event."},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["candidate"]},"email":{"type":"string"},"display_name":{"type":"string","nullable":true},"url":{"type":"string","nullable":true,"format":"uri"},"created_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"updated_at":{"type":"string","nullable":true,"description":"ISO-8601 UTC timestamp with second precision (…Z)."},"revision":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["id","object","email","display_name","url","created_at","updated_at","revision"],"description":"V1 Candidate snapshot. Explicit identity allowlist plus public talent profile URL when handle exists; never resumes, applications, or marketing permission."},"changed_fields":{"type":"array","items":{"type":"string","enum":["email","display_name","url"]},"description":"Closed Candidate changed_fields vocabulary for candidate.updated."}},"required":["object","changed_fields"]}},"required":["id","object","type","schema_version","occurred_at","board_id","data"],"example":{"id":"evt_01EXAMPLECANDIDATEUPDATED","object":"event","type":"candidate.updated","schema_version":"1","occurred_at":"2026-08-03T13:00:00Z","board_id":"acc_01EXAMPLEBOARD","data":{"object":{"id":"boardUsers_01EXAMPLE","object":"candidate","email":"candidate@example.test","display_name":"Updated Candidate","url":"https://example-board.cavuno.com/p/example-candidate","created_at":"2026-08-03T12:00:00Z","updated_at":"2026-08-03T13:00:00Z","revision":2},"changed_fields":["display_name"]}}},"WebhookCandidateDeletedEvent":{"type":"object","properties":{"id":{"type":"string","description":"Stable public event id (evt_…)."},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["candidate.deleted"]},"schema_version":{"type":"string","enum":["1"]},"occurred_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"board_id":{"type":"string","description":"Board account id that owns the event."},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["candidate"]},"revision":{"type":"integer","minimum":0,"exclusiveMinimum":true},"deleted":{"type":"boolean","enum":[true]},"deleted_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"email":{"type":"string"}},"required":["id","object","revision","deleted","deleted_at","email"],"description":"V1 Candidate permanent-erasure tombstone."},"changed_fields":{"type":"array","items":{"type":"string"},"maxItems":0,"description":"Empty for create/delete events."}},"required":["object","changed_fields"]}},"required":["id","object","type","schema_version","occurred_at","board_id","data"],"example":{"id":"evt_01EXAMPLECANDIDATEDELETED","object":"event","type":"candidate.deleted","schema_version":"1","occurred_at":"2026-08-03T14:00:00Z","board_id":"acc_01EXAMPLEBOARD","data":{"object":{"id":"boardUsers_01EXAMPLE","object":"candidate","revision":3,"deleted":true,"deleted_at":"2026-08-03T14:00:00Z","email":"candidate@example.test"},"changed_fields":[]}}},"WebhookCandidateProfilePointer":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["candidate.profile"]},"profile_revision":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["id","object","profile_revision"],"description":"Thin pointer for candidate.profile.updated. No profile values; pull GET /v1/candidates/{id}/profile and reject a stale profile_revision.","example":{"id":"boardUsers_01EXAMPLE","object":"candidate.profile","profile_revision":1}},"WebhookCandidateProfileChangedField":{"type":"string","enum":["profile.headline","profile.bio","profile.location","profile.country_code","skills","languages","experience","education"],"example":"profile.headline"},"WebhookCandidateProfileUpdatedEvent":{"type":"object","properties":{"id":{"type":"string","description":"Stable public event id (evt_…)."},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["candidate.profile.updated"]},"schema_version":{"type":"string","enum":["1"]},"occurred_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"board_id":{"type":"string","description":"Board account id that owns the event."},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["candidate.profile"]},"profile_revision":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["id","object","profile_revision"],"description":"Thin pointer for candidate.profile.updated. No profile values; pull GET /v1/candidates/{id}/profile and reject a stale profile_revision."},"changed_fields":{"type":"array","items":{"type":"string","enum":["profile.headline","profile.bio","profile.location","profile.country_code","skills","languages","experience","education"]},"description":"Closed Candidate profile changed_fields vocabulary for candidate.profile.updated."}},"required":["object","changed_fields"]}},"required":["id","object","type","schema_version","occurred_at","board_id","data"],"example":{"id":"evt_01EXAMPLECANDIDATEPROFILE","object":"event","type":"candidate.profile.updated","schema_version":"1","occurred_at":"2026-08-03T13:30:00Z","board_id":"acc_01EXAMPLEBOARD","data":{"object":{"id":"boardUsers_01EXAMPLE","object":"candidate.profile","profile_revision":1},"changed_fields":["profile.headline","skills"]}}},"WebhookMarketingPermissionSnapshot":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["marketing_permission"]},"email":{"type":"string","format":"email"},"display_name":{"type":"string","nullable":true},"role":{"type":"string"},"status":{"type":"string","enum":["granted","withdrawn"]},"source":{"type":"string"},"reason":{"type":"string","nullable":true,"enum":["person_request","operator_request","account_deleted"]},"granted_at":{"type":"string","nullable":true,"description":"ISO-8601 UTC timestamp with second precision (…Z)."},"withdrawn_at":{"type":"string","nullable":true,"description":"ISO-8601 UTC timestamp with second precision (…Z)."},"updated_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"revision":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["id","object","email","display_name","role","status","source","reason","granted_at","withdrawn_at","updated_at","revision"],"description":"V1 marketing-permission reconciliation snapshot, projected from the board user. Explicit allowlist; never credentials, tokens, or private Candidate data.","example":{"id":"boardUsers_01EXAMPLE","object":"marketing_permission","email":"person@example.test","display_name":"Example Person","role":"candidate","status":"granted","source":"candidate_sign_up","reason":null,"granted_at":"2026-08-03T15:00:00Z","withdrawn_at":null,"updated_at":"2026-08-03T15:00:00Z","revision":1}},"WebhookMarketingPermissionChangedField":{"type":"string","enum":["status","source","reason","granted_at","withdrawn_at"],"example":"status"},"WebhookMarketingPermissionGrantedEvent":{"type":"object","properties":{"id":{"type":"string","description":"Stable public event id (evt_…)."},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["marketing_permission.granted"]},"schema_version":{"type":"string","enum":["1"]},"occurred_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"board_id":{"type":"string","description":"Board account id that owns the event."},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["marketing_permission"]},"email":{"type":"string","format":"email"},"display_name":{"type":"string","nullable":true},"role":{"type":"string"},"status":{"type":"string","enum":["granted","withdrawn"]},"source":{"type":"string"},"reason":{"type":"string","nullable":true,"enum":["person_request","operator_request","account_deleted"]},"granted_at":{"type":"string","nullable":true,"description":"ISO-8601 UTC timestamp with second precision (…Z)."},"withdrawn_at":{"type":"string","nullable":true,"description":"ISO-8601 UTC timestamp with second precision (…Z)."},"updated_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"revision":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["id","object","email","display_name","role","status","source","reason","granted_at","withdrawn_at","updated_at","revision"],"description":"V1 marketing-permission reconciliation snapshot, projected from the board user. Explicit allowlist; never credentials, tokens, or private Candidate data."},"changed_fields":{"type":"array","items":{"type":"string","enum":["status","source","reason","granted_at","withdrawn_at"]}}},"required":["object","changed_fields"]}},"required":["id","object","type","schema_version","occurred_at","board_id","data"],"example":{"id":"evt_01EXAMPLEMARKETINGGRANT","object":"event","type":"marketing_permission.granted","schema_version":"1","occurred_at":"2026-08-03T15:00:00Z","board_id":"acc_01EXAMPLEBOARD","data":{"object":{"id":"boardUsers_01EXAMPLE","object":"marketing_permission","email":"person@example.test","display_name":"Example Person","role":"candidate","status":"granted","source":"candidate_sign_up","reason":null,"granted_at":"2026-08-03T15:00:00Z","withdrawn_at":null,"updated_at":"2026-08-03T15:00:00Z","revision":1},"changed_fields":["status","source","granted_at"]}}},"WebhookMarketingPermissionWithdrawnEvent":{"type":"object","properties":{"id":{"type":"string","description":"Stable public event id (evt_…)."},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["marketing_permission.withdrawn"]},"schema_version":{"type":"string","enum":["1"]},"occurred_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"board_id":{"type":"string","description":"Board account id that owns the event."},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["marketing_permission"]},"email":{"type":"string","format":"email"},"display_name":{"type":"string","nullable":true},"role":{"type":"string"},"status":{"type":"string","enum":["granted","withdrawn"]},"source":{"type":"string"},"reason":{"type":"string","nullable":true,"enum":["person_request","operator_request","account_deleted"]},"granted_at":{"type":"string","nullable":true,"description":"ISO-8601 UTC timestamp with second precision (…Z)."},"withdrawn_at":{"type":"string","nullable":true,"description":"ISO-8601 UTC timestamp with second precision (…Z)."},"updated_at":{"type":"string","description":"ISO-8601 UTC timestamp with second precision (…Z)."},"revision":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["id","object","email","display_name","role","status","source","reason","granted_at","withdrawn_at","updated_at","revision"],"description":"V1 marketing-permission reconciliation snapshot, projected from the board user. Explicit allowlist; never credentials, tokens, or private Candidate data."},"changed_fields":{"type":"array","items":{"type":"string","enum":["status","source","reason","granted_at","withdrawn_at"]}}},"required":["object","changed_fields"]}},"required":["id","object","type","schema_version","occurred_at","board_id","data"],"example":{"id":"evt_01EXAMPLEMARKETINGWITHDRAWAL","object":"event","type":"marketing_permission.withdrawn","schema_version":"1","occurred_at":"2026-08-03T16:00:00Z","board_id":"acc_01EXAMPLEBOARD","data":{"object":{"id":"boardUsers_01EXAMPLE","object":"marketing_permission","email":"person@example.test","display_name":"Example Person","role":"candidate","status":"withdrawn","source":"notification_preferences","reason":"person_request","granted_at":"2026-08-03T15:00:00Z","withdrawn_at":"2026-08-03T16:00:00Z","updated_at":"2026-08-03T16:00:00Z","revision":2},"changed_fields":["status","source","reason","withdrawn_at"]}}},"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"]},"ProfileCustomFieldDefinition":{"type":"object","properties":{"key":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_-]{0,63}$"},"label":{"type":"string"},"helpText":{"type":"string","maxLength":240},"type":{"type":"string","enum":["short_text","long_text","rich_text","single_select","multi_select","boolean","number","date","url","email","phone","image_gallery","file"]},"required":{"type":"boolean"},"visibility":{"type":"string","enum":["private","public"]},"editableByOwner":{"type":"boolean"},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_-]{0,63}$"},"label":{"type":"string"}},"required":["key","label"]}},"min":{"type":"number"},"max":{"type":"number"}},"required":["key","label","type","required","visibility","editableByOwner"],"additionalProperties":false},"ReplaceProfileFieldDefinitionsBody":{"type":"object","properties":{"definitions":{"type":"array","items":{"$ref":"#/components/schemas/ProfileCustomFieldDefinition"}}},"required":["definitions"],"additionalProperties":false},"ProfileFieldValuesResponse":{"type":"object","properties":{"definitions":{"type":"array","items":{"$ref":"#/components/schemas/ProfileCustomFieldDefinition"}},"values":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}}]}}},"required":["definitions","values"]},"ProfileFieldValuesBody":{"type":"object","properties":{"values":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}},{"nullable":true}]}}},"required":["values"],"additionalProperties":false},"ProfileObjectReferenceDefinition":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"typeId":{"type":"string","minLength":1},"multiple":{"type":"boolean"},"maxSelections":{"type":"integer","minimum":1,"maximum":100,"description":"Operator-set maximum number of entries a profile can select. Only meaningful when `multiple` is true; absent means the system ceiling of 100."},"required":{"type":"boolean","description":"Whether a profile must select at least one entry when this field is shown."},"visibility":{"type":"string","enum":["private","public"]},"editableByOwner":{"type":"boolean"},"allowOverrides":{"type":"boolean"},"descriptionFieldKey":{"type":"string"},"valueDefinitions":{"type":"array","items":{"$ref":"#/components/schemas/ScalarProfileCustomFieldDefinition"}},"entryDefinitions":{"type":"array","items":{"$ref":"#/components/schemas/ScalarProfileCustomFieldDefinition"}}},"required":["key","label","typeId","multiple","visibility","editableByOwner","allowOverrides"]},"ScalarProfileCustomFieldDefinition":{"allOf":[{"$ref":"#/components/schemas/ProfileCustomFieldDefinition"},{"type":"object","properties":{"type":{"type":"string","enum":["short_text","long_text","rich_text","single_select","multi_select","boolean","number","date","url","email","phone"]}},"additionalProperties":false}]},"ProfileObjectReferencesResult":{"type":"object","properties":{"definitions":{"type":"array","items":{"$ref":"#/components/schemas/ProfileObjectReferenceDefinition"}},"selections":{"type":"array","items":{"$ref":"#/components/schemas/ResolvedProfileObjectReference"}}},"required":["definitions","selections"]},"ResolvedProfileObjectReference":{"type":"object","properties":{"fieldKey":{"type":"string"},"fieldLabel":{"type":"string"},"recordId":{"type":"string","minLength":1},"slug":{"type":"string","description":"URL-safe identifier, unique within the collection. Changing it keeps the previous value reserved."},"title":{"type":"string"},"description":{"type":"string"},"titleOverride":{"type":"string"},"descriptionOverride":{"type":"string"},"logoUrl":{"type":"string","description":"The entry's logo: the image in the collection's logo field, or a legacy logo URL on older entries. Absent when the entry has neither."},"descriptionType":{"type":"string","enum":["rich_text"]},"descriptionFieldKey":{"type":"string"},"fields":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"type":{"type":"string","enum":["short_text","long_text","rich_text","single_select","multi_select","boolean","number","date","url","email","phone","image","image_gallery","file","reference"]},"helpText":{"type":"string"},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"}},"required":["key","label"]}}},"required":["key","label","type"]}},"attributes":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"boolean"},{"type":"number"},{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"contentType":{"type":"string"},"sizeBytes":{"type":"number"},"url":{"type":"string"}},"required":["id","name","contentType","sizeBytes","url"]},{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"contentType":{"type":"string"},"sizeBytes":{"type":"number"},"url":{"type":"string"}},"required":["id","name","contentType","sizeBytes","url"]}}]}},"references":{"type":"object","additionalProperties":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string","description":"URL-safe identifier, unique within the collection. Changing it keeps the previous value reserved."},"fields":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"type":{"type":"string","enum":["short_text","long_text","rich_text","single_select","multi_select","boolean","number","date","url","email","phone","image","image_gallery","file","reference"]},"helpText":{"type":"string"},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"}},"required":["key","label"]}}},"required":["key","label","type"]}},"values":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"boolean"},{"type":"number"},{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"contentType":{"type":"string"},"sizeBytes":{"type":"number"},"url":{"type":"string"}},"required":["id","name","contentType","sizeBytes","url"]},{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"contentType":{"type":"string"},"sizeBytes":{"type":"number"},"url":{"type":"string"}},"required":["id","name","contentType","sizeBytes","url"]}}]}}},"required":["id","name","fields","values"]}}},"valueDefinitions":{"type":"array","items":{"$ref":"#/components/schemas/ScalarProfileCustomFieldDefinition"}},"entryDefinitions":{"type":"array","items":{"$ref":"#/components/schemas/ScalarProfileCustomFieldDefinition"}},"values":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}}]}},"entries":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"values":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}}]}}},"required":["key","values"]}}},"required":["fieldKey","fieldLabel","recordId","title","fields","attributes","valueDefinitions","entryDefinitions","values","entries"]},"ReplaceProfileObjectReferenceSelectionsBody":{"type":"object","properties":{"selections":{"type":"array","items":{"$ref":"#/components/schemas/ProfileObjectReferenceSelectionWrite"},"maxItems":500}},"required":["selections"],"additionalProperties":false},"ProfileObjectReferenceSelectionWrite":{"type":"object","properties":{"fieldKey":{"type":"string"},"recordId":{"type":"string","minLength":1},"titleOverride":{"type":"string","nullable":true,"maxLength":2000},"descriptionOverride":{"type":"string","nullable":true,"maxLength":2000},"values":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}}]}},"entries":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"values":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}}]}}},"required":["key","values"]},"maxItems":100}},"required":["fieldKey","recordId"]},"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","custom_objects.records_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"},"result":{"type":"object","nullable":true,"properties":{"totalRows":{"type":"number"},"created":{"type":"number"},"updated":{"type":"number"},"failed":{"type":"number"},"errors":{"type":"array","items":{"type":"object","properties":{"rowIndex":{"type":"number"},"code":{"type":"string"},"message":{"type":"string"}},"required":["rowIndex","code","message"]}}},"required":["totalRows","created","updated","failed","errors"],"description":"A safe workflow result summary when the operation kind publishes one."},"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","custom_object_type"]},"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"]},"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."},"CandidateSyncSnapshot":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the candidate."},"email":{"type":"string","description":"The candidate's email address."},"displayName":{"type":"string","nullable":true,"description":"The candidate's display name."},"revision":{"type":"integer","minimum":0,"description":"Monotonic Candidate lifecycle revision."},"profileRevision":{"type":"integer","minimum":0,"description":"Monotonic profile-projection revision."},"deactivatedAt":{"type":"string","nullable":true,"format":"date-time","description":"ISO 8601 timestamp when sign-in was disabled, or `null` when active."},"profile":{"type":"object","properties":{"headline":{"type":"string","nullable":true},"bio":{"type":"string","nullable":true},"location":{"type":"string","nullable":true},"countryCode":{"type":"string","nullable":true}},"required":["headline","bio","location","countryCode"]},"skills":{"type":"array","items":{"type":"string"}},"languages":{"type":"array","items":{"$ref":"#/components/schemas/CandidateSyncSnapshotLanguage"}},"experience":{"type":"array","items":{"$ref":"#/components/schemas/CandidateSyncSnapshotExperience"}},"education":{"type":"array","items":{"$ref":"#/components/schemas/CandidateSyncSnapshotEducation"}}},"required":["id","email","displayName","revision","profileRevision","deactivatedAt","profile","skills","languages","experience","education"]},"CandidateSyncSnapshotLanguage":{"type":"object","properties":{"name":{"type":"string"},"proficiency":{"type":"string"},"sortOrder":{"type":"integer"}},"required":["name","proficiency","sortOrder"]},"CandidateSyncSnapshotExperience":{"type":"object","properties":{"title":{"type":"string"},"companyName":{"type":"string"},"companyUrl":{"type":"string","nullable":true},"location":{"type":"string","nullable":true},"employmentType":{"type":"string","nullable":true},"locationType":{"type":"string","nullable":true},"foundVia":{"type":"string","nullable":true},"startDate":{"type":"string"},"endDate":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"experienceSkills":{"type":"array","nullable":true,"items":{"type":"string"}},"sortOrder":{"type":"integer"}},"required":["title","companyName","companyUrl","location","employmentType","locationType","foundVia","startDate","endDate","description","experienceSkills","sortOrder"]},"CandidateSyncSnapshotEducation":{"type":"object","properties":{"institutionName":{"type":"string"},"institutionUrl":{"type":"string","nullable":true},"degree":{"type":"string","nullable":true},"fieldOfStudy":{"type":"string","nullable":true},"grade":{"type":"string","nullable":true},"activitiesAndSocieties":{"type":"string","nullable":true},"startDate":{"type":"string","nullable":true},"endDate":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"sortOrder":{"type":"integer"}},"required":["institutionName","institutionUrl","degree","fieldOfStudy","grade","activitiesAndSocieties","startDate","endDate","description","sortOrder"]},"CandidateProfileProjection":{"type":"object","properties":{"headline":{"type":"string","nullable":true,"description":"Absent key leaves the stored headline unchanged; `null` clears it."},"bio":{"type":"string","nullable":true,"description":"Absent key leaves the stored bio unchanged; `null` clears it."},"location":{"type":"string","nullable":true,"description":"Absent key leaves the stored location unchanged; `null` clears it."},"countryCode":{"type":"string","nullable":true,"description":"Absent key leaves the stored country code unchanged; `null` clears it. Ignored without an error while the candidate has a home place that this request keeps (a changed `location` removes it): the country code is then that place's country."},"skills":{"type":"array","items":{"type":"string"},"maxItems":200,"description":"Absent key leaves the stored skills unchanged. Providing an array replaces the collection wholesale (empty array clears). Maximum 200 rows."},"languages":{"type":"array","items":{"$ref":"#/components/schemas/CandidateProfileLanguageProjection"},"maxItems":50,"description":"Absent key leaves the stored languages unchanged. Providing an array replaces the collection wholesale (empty array clears). Maximum 50 rows."},"experience":{"type":"array","items":{"$ref":"#/components/schemas/CandidateProfileExperienceProjection"},"maxItems":50,"description":"Absent key leaves the stored experience unchanged. Providing an array replaces the collection wholesale (empty array clears). Maximum 50 rows."},"education":{"type":"array","items":{"$ref":"#/components/schemas/CandidateProfileEducationProjection"},"maxItems":50,"description":"Absent key leaves the stored education unchanged. Providing an array replaces the collection wholesale (empty array clears). Maximum 50 rows."}},"additionalProperties":false},"CandidateProfileLanguageProjection":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"Language name."},"proficiency":{"type":"string","minLength":1,"description":"Proficiency label."},"sortOrder":{"type":"integer","description":"Display order, lower first."}},"required":["name","proficiency","sortOrder"],"additionalProperties":false},"CandidateProfileExperienceProjection":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"Job title."},"companyName":{"type":"string","minLength":1,"description":"Employer name."},"companyUrl":{"type":"string","nullable":true,"description":"Employer URL."},"location":{"type":"string","nullable":true,"description":"Role location."},"employmentType":{"type":"string","nullable":true,"description":"Employment type."},"locationType":{"type":"string","nullable":true,"description":"Location type."},"foundVia":{"type":"string","nullable":true,"description":"How the role was found."},"startDate":{"type":"string","minLength":1,"description":"Start date."},"endDate":{"type":"string","nullable":true,"description":"End date."},"description":{"type":"string","nullable":true,"description":"Role description."},"experienceSkills":{"type":"array","nullable":true,"items":{"type":"string"},"maxItems":50,"description":"Per-role skills; replaced with the row."},"sortOrder":{"type":"integer","description":"Display order, lower first."}},"required":["title","companyName","startDate","sortOrder"],"additionalProperties":false},"CandidateProfileEducationProjection":{"type":"object","properties":{"institutionName":{"type":"string","minLength":1,"description":"Institution name."},"institutionUrl":{"type":"string","nullable":true,"description":"Institution URL."},"degree":{"type":"string","nullable":true,"description":"Degree awarded."},"fieldOfStudy":{"type":"string","nullable":true,"description":"Field of study."},"grade":{"type":"string","nullable":true,"description":"Grade or GPA."},"activitiesAndSocieties":{"type":"string","nullable":true,"description":"Activities and societies."},"startDate":{"type":"string","nullable":true,"description":"Start date."},"endDate":{"type":"string","nullable":true,"description":"End date."},"description":{"type":"string","nullable":true,"description":"Education description."},"sortOrder":{"type":"integer","description":"Display order, lower first."}},"required":["institutionName","sortOrder"],"additionalProperties":false},"CandidateDetail":{"allOf":[{"$ref":"#/components/schemas/Candidate"},{"type":"object","properties":{"deactivatedAt":{"type":"string","nullable":true,"format":"date-time","description":"ISO 8601 timestamp when sign-in was disabled, or `null` when the candidate can sign in. Deactivate revokes all sessions, blocks sign-in, and hides the profile from talent surfaces; profile and application history are preserved. Reactivate restores sign-in and talent-surface visibility; the candidate signs in again to establish a new session."},"profile":{"$ref":"#/components/schemas/AdminCandidateProfile"},"savedJobCount":{"type":"number","description":"Number of jobs the candidate has saved. Values are capped at 1,000 in write-operation responses (reconcile/deactivate/reactivate/create/update); GET detail returns 422 `candidate_resource_limit` beyond the cap."},"alertCount":{"type":"number","description":"Number of job alerts the candidate has. Values are capped at 1,000 in write-operation responses (reconcile/deactivate/reactivate/create/update); GET detail returns 422 `candidate_resource_limit` beyond the cap."},"resume":{"$ref":"#/components/schemas/CandidateResumeFile"}},"required":["deactivatedAt","profile","savedJobCount","alertCount","resume"]}]},"AdminCandidateProfile":{"type":"object","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."},"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)."},"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."},"candidateCreatedAt":{"type":"string","description":"ISO-8601 timestamp when this Board user became an operator-visible Candidate. This is the reconciliation counterpart of candidate.created, not newsletter permission."},"updatedAt":{"type":"string","nullable":true,"description":"ISO-8601 timestamp of the latest approved Candidate identity update, or null for older rows."},"revision":{"type":"integer","minimum":0,"description":"Monotonic Candidate lifecycle revision; legacy rows are 0 until the rollout migration runs."},"lastActiveAt":{"type":"string","nullable":true,"description":"ISO-8601 timestamp of the last activity on the board (a sign-in or signed-in use), to the hour, or `null`."}},"required":["id","object","email","displayName","handle","avatarUrl","hasResume","createdAt","candidateCreatedAt","updatedAt","revision","lastActiveAt"]},"CreateCandidateBody":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"The candidate's email address. Must be unique on the account."},"displayName":{"type":"string","minLength":1,"description":"The candidate's display name."},"profile":{"allOf":[{"$ref":"#/components/schemas/CandidateProfileProjection"},{"description":"Optional initial profile projection. Seeded once at create; the Candidate owns it afterwards unless a later sync source claims the group. Absent keys are left unset; `null` on a scalar clears it."}]}},"required":["email","displayName"],"additionalProperties":false},"UpdateCandidateBody":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"Absent key leaves the stored email unchanged. The new address must be unique on the account."},"displayName":{"type":"string","minLength":1,"description":"Absent key leaves the stored display name unchanged."}},"additionalProperties":false},"CandidateReconcileResult":{"type":"object","properties":{"status":{"type":"string","enum":["created","updated","unchanged","upgraded"],"description":"`created` when a new Candidate is provisioned, `updated` when identity or profile changed, `unchanged` when the source revision was already applied, `upgraded` when an existing non-candidate Board user became a Candidate."},"candidate":{"allOf":[{"$ref":"#/components/schemas/CandidateDetail"},{"description":"The candidate after this reconcile, same serialization as `GET /candidates/{id}` (including `deactivatedAt`)."}]}},"required":["status","candidate"]},"ReconcileCandidateBody":{"type":"object","properties":{"sourceKey":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9._-]+$","description":"Opaque caller-chosen identifier for the membership system this write comes from (1–64 characters, `[a-z0-9._-]`). Identifies the source, not the person, and must stay stable: changing it treats the caller as a new source and cannot update an existing link."},"externalMemberId":{"type":"string","minLength":1,"maxLength":256,"description":"The member id in the caller's system (1–256 characters). Sent in the body, never the URL: request paths land in logs and traces. Together with `sourceKey` this is the idempotent membership-sync key."},"sourceRevision":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Monotonically increasing revision per member, typically the source system's change timestamp in milliseconds. An equal revision is an idempotent no-op (`unchanged`); a lower revision is rejected as stale so a delayed write can never resurrect stale profile data or reactivate a deactivated account. Revisions above 2^53-1 are rejected."},"email":{"type":"string","format":"email","description":"The candidate's email address. Used to create or link the Board user for this membership source."},"displayName":{"type":"string","minLength":1,"description":"The candidate's display name."},"profile":{"allOf":[{"$ref":"#/components/schemas/CandidateProfileProjection"},{"description":"Optional bounded profile projection, the same shape as `PUT /candidates/{id}/profile`. Absent keys are left unchanged; `null` on a scalar clears it; a provided collection array replaces that collection wholesale. Pair with `candidate.profile.updated` and `GET /candidates/{id}/profile` for notification-plus-pull."}]},"active":{"type":"boolean","description":"When `false`, deactivates the candidate (sign-in disabled, sessions revoked, profile hidden from talent surfaces). When `true`, restores sign-in and talent-surface visibility; the candidate signs in again to establish a new session. Profile and application history are preserved either way."}},"required":["sourceKey","externalMemberId","sourceRevision","email","displayName","active"],"additionalProperties":false},"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."},"instagramUrl":{"type":"string","nullable":true,"description":"Instagram profile 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."},"revision":{"type":"integer","minimum":0,"description":"Public Company lifecycle revision. Historical rows may be 0 until rollout backfill."},"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","instagramUrl","createdAt","updatedAt","revision","links"]},"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"]},"Company":{"allOf":[{"$ref":"#/components/schemas/CompanySummary"},{"type":"object","properties":{"description":{"type":"string","nullable":true,"description":"Long-form description of the company (HTML), 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"]}]},"CreateCompanyBody":{"type":"object","properties":{"website":{"type":"string","nullable":true,"maxLength":200,"description":"Public company website URL. Normalized to a canonical apex domain when stored. `null` or `\"\"` means not set."},"summary":{"type":"string","nullable":true,"maxLength":280,"description":"One-line summary of the company. Up to 280 characters. `null` or `\"\"` means not set."},"description":{"type":"string","nullable":true,"maxLength":25000,"description":"Long-form description of the company, as HTML. Up to 25,000 characters. The HTML is sanitized on write: tags and attributes outside the supported formatting set (paragraphs, headings, lists, links, inline emphasis) are removed. Plain text without HTML tags is converted to paragraphs. `null` or `\"\"` means not set."},"xUrl":{"type":"string","nullable":true,"maxLength":500,"description":"X (Twitter) profile URL or handle. Stored as the canonical handle. `null` or `\"\"` means not set."},"linkedinUrl":{"type":"string","nullable":true,"maxLength":500,"description":"LinkedIn company page URL. `null` or `\"\"` means not set."},"facebookUrl":{"type":"string","nullable":true,"maxLength":500,"description":"Facebook company page URL. `null` or `\"\"` means not set."},"instagramUrl":{"type":"string","nullable":true,"maxLength":500,"description":"Instagram profile URL or handle. `null` or `\"\"` means 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. 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},"FindOrCreateCompanyBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120,"description":"The company's display name."},"website":{"type":"string","nullable":true,"maxLength":200,"description":"Public company website URL. Used to resolve to an existing company by domain before falling back to creation. `null` or `\"\"` means not set."},"summary":{"type":"string","nullable":true,"maxLength":280,"description":"One-line summary of the company. Up to 280 characters. `null` or `\"\"` means not set."},"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},"UpdateCompanyBody":{"type":"object","properties":{"website":{"type":"string","nullable":true,"maxLength":200,"description":"Public company website URL. Normalized to a canonical apex domain when stored. Pass `null` or `\"\"` to clear the stored value; omitted means unchanged."},"summary":{"type":"string","nullable":true,"maxLength":280,"description":"One-line summary of the company. Up to 280 characters. Pass `null` or `\"\"` to clear the stored value; omitted means unchanged."},"description":{"type":"string","nullable":true,"maxLength":25000,"description":"Long-form description of the company, as HTML. Up to 25,000 characters. The HTML is sanitized on write: tags and attributes outside the supported formatting set (paragraphs, headings, lists, links, inline emphasis) are removed. Plain text without HTML tags is converted to paragraphs. Pass `null` or `\"\"` to clear the stored value; omitted means unchanged."},"xUrl":{"type":"string","nullable":true,"maxLength":500,"description":"X (Twitter) profile URL or handle. Stored as the canonical handle. Pass `null` or `\"\"` to clear the stored value; omitted means unchanged."},"linkedinUrl":{"type":"string","nullable":true,"maxLength":500,"description":"LinkedIn company page URL. Pass `null` or `\"\"` to clear the stored value; omitted means unchanged."},"facebookUrl":{"type":"string","nullable":true,"maxLength":500,"description":"Facebook company page URL. Pass `null` or `\"\"` to clear the stored value; omitted means unchanged."},"instagramUrl":{"type":"string","nullable":true,"maxLength":500,"description":"Instagram profile URL or handle. Pass `null` or `\"\"` to clear the stored value; omitted means unchanged."},"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},"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."},"customFields":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"maxLength":64},"values":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]},"minItems":1,"maxItems":10}},"required":["key","values"],"additionalProperties":false},"maxItems":10,"description":"Match every public custom-field clause; values within one clause are alternatives."},"objectReferences":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"maxLength":64},"recordIds":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"maxItems":10}},"required":["key","recordIds"],"additionalProperties":false},"maxItems":10,"description":"Match every public object-reference clause; record IDs within one clause are alternatives."}},"additionalProperties":false}},"additionalProperties":false},"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"]}]},"MediaUploadIntent":{"type":"object","properties":{"id":{"type":"string","description":"Opaque staged media upload intent identifier."},"object":{"type":"string","enum":["media_upload_intent"]},"uploadUrl":{"type":"string","format":"uri","description":"Short-lived URL that accepts the original raw file bytes."},"expiresAt":{"type":"string","format":"date-time"}},"required":["id","object","uploadUrl","expiresAt"]},"MediaUploadIntentCreate":{"type":"object","properties":{"filename":{"type":"string","minLength":1,"maxLength":255},"mimeType":{"type":"string","minLength":1,"maxLength":255},"sizeBytes":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":10485760},"purpose":{"type":"string","enum":["board_logo","board_hero","account_avatar","company_logo","blog_image"]},"resourceType":{"type":"string","minLength":1,"maxLength":128},"resourceId":{"type":"string","minLength":1,"maxLength":512}},"required":["filename","mimeType","sizeBytes","purpose"]},"MediaUploadIntentComplete":{"type":"object","properties":{"stagingStorageId":{"type":"string","minLength":1,"description":"The storageId returned after POSTing the raw file to the intent uploadUrl."}},"required":["stagingStorageId"]},"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},"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"],"description":"Deprecated. Prefer plans with purpose employer_service and pricingMode contact."},"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,"description":"Deprecated. Prefer creating a plan with purpose employer_service and pricingMode contact."},"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,"description":"Deprecated. Prefer updating the corresponding employer-service contact plan."},"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},"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},"OperatorSettingsConfig":{"type":"object","properties":{"passwordProtectionEnabled":{"type":"boolean"},"jobAlertsEnabled":{"type":"boolean"},"jobRecommendationsEnabled":{"type":"boolean"},"recommendedTalentEnabled":{"type":"boolean"},"candidatesEnabled":{"type":"boolean"},"employersEnabled":{"type":"boolean"},"blogEnabled":{"type":"boolean"},"impressumEnabled":{"type":"boolean"},"requireApprovalFreeJobs":{"type":"boolean"},"postingRequiresMembership":{"type":"boolean"},"requireApprovalAggregatedJobs":{"type":"boolean"},"registrationWallEnabled":{"type":"boolean"},"nativeApplicationsEnabled":{"type":"boolean"},"countryGatingMode":{"type":"string","enum":["sponsored_only","all_jobs"],"description":"Apply country gate mode. sponsored_only is the minimum mode for Sponsored inventory."},"applicantMessagingEnabled":{"type":"boolean"},"applyUrlAttribution":{"$ref":"#/components/schemas/ApplyUrlAttribution"},"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},"companyInstagramUrl":{"type":"string","nullable":true},"ga4MeasurementId":{"type":"string","nullable":true},"gtmContainerId":{"type":"string","nullable":true},"metaPixelId":{"type":"string","nullable":true},"linkedinPartnerId":{"type":"string","nullable":true},"linkedinConversionSignUpId":{"type":"string","nullable":true},"linkedinConversionLoginId":{"type":"string","nullable":true},"linkedinConversionApplyClickId":{"type":"string","nullable":true},"linkedinConversionApplySubmitId":{"type":"string","nullable":true},"linkedinConversionJobAlertSubscribeId":{"type":"string","nullable":true},"passwordProtectionMessage":{"type":"string","nullable":true,"deprecated":true,"description":"Deprecated: no longer shown on the password gate. Gate copy now lives on the board's builder-designed coming-soon page. Still accepted and returned for compatibility; it will be removed with the hosted board."},"defaultJobDurationDays":{"type":"integer","minimum":0,"exclusiveMinimum":true},"talentDirectoryVisibility":{"type":"string","enum":["off","public","employers_only"]},"defaultCandidateProfileVisibility":{"type":"string","enum":["hidden","logged_in_only","public"]},"signInMethods":{"$ref":"#/components/schemas/SignInMethods"}},"required":["jobRecommendationsEnabled","recommendedTalentEnabled","signInMethods"],"additionalProperties":false},"ApplyUrlAttribution":{"oneOf":[{"type":"object","properties":{"mode":{"type":"string","enum":["off"]}},"required":["mode"],"additionalProperties":false},{"type":"object","properties":{"mode":{"type":"string","enum":["append"]},"params":{"type":"array","items":{"$ref":"#/components/schemas/ApplyUrlParamTemplate"},"maxItems":8}},"required":["mode","params"],"additionalProperties":false}],"description":"Query parameters appended to outbound apply URLs. Absent means the default `ref={{boardHost}}`."},"ApplyUrlParamTemplate":{"type":"object","properties":{"key":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[A-Za-z0-9][A-Za-z0-9_.:-]*$"},"valueTemplate":{"type":"string","maxLength":200}},"required":["key","valueTemplate"],"additionalProperties":false},"SignInMethods":{"type":"object","properties":{"candidate":{"$ref":"#/components/schemas/BuiltInSignInMethods"},"employer":{"$ref":"#/components/schemas/BuiltInSignInMethods"}},"required":["candidate","employer"],"additionalProperties":false,"description":"Which built-in sign-in methods are switched on for candidates and for employers. SSO connections are switched on per role on `/sso-connections`."},"BuiltInSignInMethods":{"type":"object","properties":{"password":{"type":"boolean","description":"Email and password."},"magicLink":{"type":"boolean","description":"Emailed one-time sign-in link."},"google":{"type":"boolean","description":"Sign in with Google."},"linkedin":{"type":"boolean","description":"Sign in with LinkedIn."}},"required":["password","magicLink","google","linkedin"],"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."},"jobRecommendationsEnabled":{"type":"boolean","description":"Whether signed-in candidates can see personalized job recommendations. Absent board config defaults to `true`."},"recommendedTalentEnabled":{"type":"boolean","description":"Whether employers can see recommended talent matches for their jobs. Absent board config defaults to `false`."},"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."},"postingRequiresMembership":{"type":"boolean","description":"When true, only companies with an active plan assignment can post jobs. Absent means anyone can post."},"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`."},"countryGatingMode":{"type":"string","enum":["sponsored_only","all_jobs"],"description":"Apply country gate mode. The default is sponsored_only; all_jobs also gates ordinary external and native starter applies."},"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`."},"applyUrlAttribution":{"allOf":[{"$ref":"#/components/schemas/ApplyUrlAttribution"},{"description":"Query parameters appended to outbound apply URLs. `{ \"mode\": \"off\" }` appends nothing — use it for boards whose upstream application host rejects unexpected query parameters. `{ \"mode\": \"append\", \"params\": [...] }` sets the parameters explicitly; each `valueTemplate` may contain the `{{boardHost}}`, `{{boardSlug}}` and `{{boardName}}` tokens. An `append` policy with an empty `params` array is stored as `off`. Absent board config means the default `ref={{boardHost}}`. Individual import feeds can override this per feed."}]},"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`."},"defaultCandidateProfileVisibility":{"type":"string","enum":["hidden","logged_in_only","public"],"description":"Visibility a candidate profile is created with at signup: `hidden` (not listed), `logged_in_only` (signed-in visitors), or `public`. Defaults to `hidden`, which matches what an unset value already means — the talent directory lists only `public` and `logged_in_only` profiles. Applies at signup ONLY: it never rewrites an existing profile, and a candidate can change their own afterwards. Composes with `talentDirectoryVisibility`, which controls who may browse the directory at all."},"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}],"description":"Public contact email shown on the board. Pass `null` to clear."},"companyLegalName":{"anyOf":[{"type":"string","maxLength":200},{"type":"string","enum":[""]},{"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}],"description":"Postal address of the entity operating the board. Pass `null` to clear."},"companyWebsiteUrl":{"anyOf":[{"type":"string","maxLength":500},{"type":"string","enum":[""]},{"nullable":true}],"description":"Public company website URL. Pass `null` to clear."},"companyXHandle":{"anyOf":[{"type":"string","maxLength":500},{"type":"string","enum":[""]},{"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}],"description":"Company Facebook page URL. Pass `null` to clear."},"companyLinkedinUrl":{"anyOf":[{"type":"string","maxLength":500},{"type":"string","enum":[""]},{"nullable":true}],"description":"Company LinkedIn page URL. Pass `null` to clear."},"companyInstagramUrl":{"anyOf":[{"type":"string","maxLength":500},{"type":"string","enum":[""]},{"nullable":true}],"description":"Company Instagram handle or profile URL. Pass `null` to clear."},"ga4MeasurementId":{"type":"string","nullable":true,"maxLength":120,"pattern":"^[A-Za-z0-9_-]*$","description":"Google Analytics 4 measurement ID (for example `G-XXXXXXXXXX`) loaded on the public board. Letters, digits, `-` and `_`, up to 120 characters. Pass `null` or an empty string to clear."},"gtmContainerId":{"type":"string","nullable":true,"maxLength":120,"pattern":"^[A-Za-z0-9_-]*$","description":"Google Tag Manager container ID (for example `GTM-XXXXXXX`) loaded on the public board. Letters, digits, `-` and `_`, up to 120 characters. Pass `null` or an empty string to clear."},"metaPixelId":{"type":"string","nullable":true,"maxLength":120,"pattern":"^[A-Za-z0-9_-]*$","description":"Meta Pixel ID loaded on the public board. Letters, digits, `-` and `_`, up to 120 characters. Pass `null` or an empty string to clear."},"linkedinPartnerId":{"type":"string","nullable":true,"maxLength":120,"pattern":"^[A-Za-z0-9_-]*$","description":"LinkedIn Insight Tag partner ID loaded on the public board. Letters, digits, `-` and `_`, up to 120 characters. Pass `null` or an empty string to clear."},"linkedinConversionSignUpId":{"type":"string","nullable":true,"maxLength":120,"pattern":"^[A-Za-z0-9_-]*$","description":"LinkedIn conversion ID fired when a visitor signs up. Letters, digits, `-` and `_`, up to 120 characters. Pass `null` or an empty string to clear."},"linkedinConversionLoginId":{"type":"string","nullable":true,"maxLength":120,"pattern":"^[A-Za-z0-9_-]*$","description":"LinkedIn conversion ID fired when a visitor signs in. Letters, digits, `-` and `_`, up to 120 characters. Pass `null` or an empty string to clear."},"linkedinConversionApplyClickId":{"type":"string","nullable":true,"maxLength":120,"pattern":"^[A-Za-z0-9_-]*$","description":"LinkedIn conversion ID fired when a visitor clicks Apply. Letters, digits, `-` and `_`, up to 120 characters. Pass `null` or an empty string to clear."},"linkedinConversionApplySubmitId":{"type":"string","nullable":true,"maxLength":120,"pattern":"^[A-Za-z0-9_-]*$","description":"LinkedIn conversion ID fired when a visitor submits an application. Letters, digits, `-` and `_`, up to 120 characters. Pass `null` or an empty string to clear."},"linkedinConversionJobAlertSubscribeId":{"type":"string","nullable":true,"maxLength":120,"pattern":"^[A-Za-z0-9_-]*$","description":"LinkedIn conversion ID fired when a visitor subscribes to job alerts. Letters, digits, `-` and `_`, up to 120 characters. Pass `null` or an empty string 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}],"deprecated":true,"description":"Deprecated: no longer shown on the password gate. Gate copy now lives on the board's builder-designed coming-soon page. Still accepted and returned for compatibility; it will be removed with the hosted board. Up to 500 characters. Pass `null` to clear."},"signInMethods":{"$ref":"#/components/schemas/SignInMethodsPatch"}},"additionalProperties":false},"SignInMethodsPatch":{"type":"object","properties":{"candidate":{"type":"object","properties":{"password":{"type":"boolean"},"magicLink":{"type":"boolean"},"google":{"type":"boolean"},"linkedin":{"type":"boolean"}},"additionalProperties":false},"employer":{"type":"object","properties":{"password":{"type":"boolean"},"magicLink":{"type":"boolean"},"google":{"type":"boolean"},"linkedin":{"type":"boolean"}},"additionalProperties":false}},"additionalProperties":false,"description":"Switch built-in sign-in methods on or off per role; omitted methods stay as they are. Switching off a role’s last way to sign in (no other built-in method on, and no tested SSO connection switched on for that role) is refused with 409 `sign_in_method_last`. People already signed in stay signed in."},"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}],"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 `:`."},"adsenseGoogleConsentMessage":{"type":"boolean","description":"Use Google's consent message (AdSense → Privacy & messaging) for visitors in the EEA, UK and Switzerland while AdSense is on. Defaults to `true`. Set `false` to show the board's own cookie banner to everyone instead; also turn off \"Maximize message coverage\" in AdSense, or European visitors may see two consent messages."},"adsTxt":{"anyOf":[{"type":"string","maxLength":2000},{"type":"string","enum":[""]},{"nullable":true}],"description":"Contents to serve from `/ads.txt`. Up to 2,000 characters. Pass an empty string or `null` to clear."}},"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}],"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}],"description":"AdSense layout type for the placement."},"format":{"anyOf":[{"type":"string","enum":["auto","horizontal","vertical","rectangle","responsive"]},{"type":"string","enum":[""]},{"nullable":true}],"description":"AdSense ad format."},"style":{"anyOf":[{"type":"string","enum":["default","light","dark","contrast"]},{"type":"string","enum":[""]},{"nullable":true}],"description":"Visual style override for the placement."},"frequency":{"anyOf":[{"type":"integer","minimum":1,"maximum":50},{"nullable":true}],"description":"How often the placement is shown (e.g. once every N items)."}},"required":["enabled","slotId"]},"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},"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"},"description":"Built-in employment types offered. Empty means every built-in, unless the board has custom types: then it means no built-in is offered, only the offered custom types."},"customTypes":{"type":"array","items":{"$ref":"#/components/schemas/JobFormCustomEmploymentType"},"description":"The board's custom employment types (at most 20)."},"order":{"type":"array","items":{"type":"string"},"description":"Display order of built-in values and custom type keys. Absent: built-ins in their standard order, then custom types. Entries it misses follow in that same order."}},"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."},"collectionFields":{"type":"array","items":{"$ref":"#/components/schemas/JobCollectionFieldDefinition"},"description":"Collection-reference job fields, in display order. Values are stored separately in each job collectionValues bag."}}},"JobFormCustomEmploymentType":{"type":"object","properties":{"key":{"type":"string","description":"Stable key, derived from the name at creation. Send it as `customEmploymentType` on `POST`/`PATCH /v1/jobs`."},"label":{"type":"string","description":"Display name, e.g. `Casual`."},"employmentType":{"type":"string","description":"The custom type's Google equivalent: a built-in employment type (Google for Jobs and feeds see this value)."},"offered":{"type":"boolean","description":"`false` when posters can no longer pick this type (jobs that use it keep its label). Absent means offered."}},"required":["key","label","employmentType"]},"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."},"helpText":{"type":"string","maxLength":240,"description":"Optional guidance displayed beside the field."},"type":{"type":"string","enum":["short_text","long_text","rich_text","single_select","multi_select","boolean","number"],"description":"Field type, which dictates the value: `short_text`/`long_text` → plain string; `rich_text` → sanitized basic HTML; `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."},"visibility":{"type":"string","enum":["public","private"],"description":"Who sees the field. `public` (or absent): the job page, employers, search and the Board API. `private`: only the board team, in the dashboard and this Operator API. Board API (`/v1/boards/...`) responses never include private fields or their values. Omitted on an existing field keeps its current visibility."}},"required":["key","label","type","required"]},"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"]},"JobCollectionFieldDefinition":{"type":"object","properties":{"key":{"type":"string","minLength":1,"maxLength":100},"label":{"type":"string","minLength":1},"typeId":{"type":"string","minLength":1},"multiple":{"type":"boolean"},"required":{"type":"boolean"},"maxSelections":{"type":"integer","minimum":1,"maximum":100,"description":"Operator-set maximum number of entries a poster can select. Only meaningful when `multiple` is true; absent means the system ceiling of 100."},"allowOverrides":{"type":"boolean","description":"Whether each job can replace a selected entry's title and description through `collectionOverrides`. Absent means false."},"descriptionFieldKey":{"type":"string","description":"Key of the collection's short, long or rich text field whose value is a selected entry's default description. When that field is rich text, an entry's `description` is sanitised HTML. Absent means entries have no default description."},"visibility":{"type":"string","enum":["public","private"],"description":"Who sees the field. `public` (or absent): the job page, employers, search and the Board API. `private`: only the board team, in the dashboard and this Operator API. Board API (`/v1/boards/...`) responses never include private fields or their values. Omitted on an existing field keeps its current visibility."}},"required":["key","label","typeId","multiple","required"]},"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},"FormLayouts":{"type":"object","properties":{"job":{"type":"array","items":{"$ref":"#/components/schemas/FormLayoutField"}},"company":{"type":"array","items":{"$ref":"#/components/schemas/FormLayoutField"}},"talent":{"type":"array","items":{"$ref":"#/components/schemas/FormLayoutField"}}},"required":["job","company","talent"],"description":"The job, company and talent forms as resolved, ordered field lists: every built-in, custom field and collection reference, including private profile fields. Fields never placed by an operator follow in the default order."},"FormLayoutField":{"type":"object","properties":{"kind":{"type":"string","enum":["builtin","custom","collection"],"description":"A built-in field, a custom field, or a collection reference."},"key":{"type":"string"},"label":{"type":"string","description":"The field label shown in Settings."},"visible":{"type":"boolean","description":"Whether the form shows the field."},"required":{"type":"boolean","description":"Whether a submission must fill the field. Always `false` for a hidden field."},"locked":{"type":"boolean","description":"A locked built-in can move but must stay shown and required. Always `false` for custom and collection fields."},"lockReason":{"$ref":"#/components/schemas/FormFieldLockReason"},"requirable":{"type":"boolean","description":"Whether a layout write can switch `required` on. Custom and collection fields take `required` from their own definition (the job-form custom-fields and profile-field endpoints), so they are never requirable here."}},"required":["kind","key","label","visible","required","locked","lockReason","requirable"]},"FormFieldLockReason":{"type":"string","nullable":true,"enum":["google_required","google_hiring_organization","google_work_arrangement","google_job_location","google_remote_eligibility","posting","identity"],"description":"Why the field is locked, or `null`."},"ReplaceFormLayoutsBody":{"type":"object","properties":{"job":{"type":"array","items":{"$ref":"#/components/schemas/FormLayoutFieldRef"},"maxItems":200,"description":"The job form, in display order."},"company":{"type":"array","items":{"$ref":"#/components/schemas/FormLayoutFieldRef"},"maxItems":200,"description":"The company profile form, in display order."},"talent":{"type":"array","items":{"$ref":"#/components/schemas/FormLayoutFieldRef"},"maxItems":200,"description":"The talent (candidate) profile form, in display order."}},"additionalProperties":false},"FormLayoutFieldRef":{"oneOf":[{"$ref":"#/components/schemas/FormLayoutBuiltinFieldRef"},{"$ref":"#/components/schemas/FormLayoutCustomFieldRef"},{"$ref":"#/components/schemas/FormLayoutCollectionFieldRef"}],"discriminator":{"propertyName":"kind","mapping":{"builtin":"#/components/schemas/FormLayoutBuiltinFieldRef","custom":"#/components/schemas/FormLayoutCustomFieldRef","collection":"#/components/schemas/FormLayoutCollectionFieldRef"}}},"FormLayoutBuiltinFieldRef":{"type":"object","properties":{"kind":{"type":"string","enum":["builtin"]},"key":{"type":"string","minLength":1,"maxLength":100,"description":"The built-in field key. Job: `employmentType`, `seniority`, `title`, `workArrangement`, `location`, `remoteEligibility`, `description`, `salary`, `applyMethod`, `company`. Company: `name`, `website`, `summary`, `xUrl`, `linkedinUrl`, `facebookUrl`, `logo`, `description`. Talent: `name`, `email`, `avatar`, `headline`, `location`, `jobSearchStatus`, `bio`, `experience`, `education`, `skills`, `languages`. New built-ins may be added; skip keys you do not recognise."},"visible":{"type":"boolean","description":"Whether the form shows the field."},"required":{"type":"boolean","description":"Whether a submission must fill the field. Only a shown, requirable built-in can be required; a locked built-in must stay shown and required."}},"required":["kind","key","visible","required"]},"FormLayoutCustomFieldRef":{"type":"object","properties":{"kind":{"type":"string","enum":["custom"]},"key":{"type":"string","minLength":1,"maxLength":100,"description":"An existing custom field key on this form."},"visible":{"type":"boolean","description":"Set `false` to hide the field; absent means shown. A field whose definition is required cannot be hidden: unset its `required` flag first."}},"required":["kind","key"]},"FormLayoutCollectionFieldRef":{"type":"object","properties":{"kind":{"type":"string","enum":["collection"]},"key":{"type":"string","minLength":1,"maxLength":100,"description":"An existing collection reference key on this form."},"visible":{"type":"boolean","description":"Set `false` to hide the field; absent means shown. A field whose definition is required cannot be hidden: unset its `required` flag first."}},"required":["kind","key"]},"SsoConnection":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the SSO connection."},"object":{"type":"string","enum":["sso_connection"]},"protocol":{"type":"string","enum":["oidc","oauth2_userinfo","saml"]},"label":{"type":"string"},"provider":{"type":"string","nullable":true,"enum":["okta","generic_oidc","generic_oauth2"],"description":"The identity provider the connection is for: `okta`, or `generic_oidc` / `generic_oauth2` for any other provider that supports OpenID Connect or OAuth 2.0. Only used to name the provider in the dashboard’s setup steps; it does not change how sign-in works."},"issuer":{"type":"string","description":"The provider issuer URL; empty on a draft not set up yet."},"status":{"type":"string","enum":["draft","tested","enabled","disabled"],"description":"Deprecated: use liveConfigTested and offeredToCandidates/offeredToEmployers."},"candidateSignInMode":{"type":"string","enum":["off","available","required"],"description":"Deprecated: use per-role connection switches and settings.signInMethods instead."},"employerSignInMode":{"type":"string","enum":["off","available","required"],"description":"Deprecated: use per-role connection switches and settings.signInMethods instead."},"discoveryUrl":{"type":"string","nullable":true},"authorizationEndpoint":{"type":"string","nullable":true},"tokenEndpoint":{"type":"string","nullable":true},"userinfoEndpoint":{"type":"string","nullable":true},"jwksUri":{"type":"string","nullable":true},"scopes":{"type":"array","nullable":true,"items":{"type":"string"}},"clientId":{"type":"string","description":"The client ID; empty on a draft not set up yet."},"hasClientSecret":{"type":"boolean","description":"Whether a client secret is stored. The secret is never returned."},"claimNames":{"$ref":"#/components/schemas/SsoConnectionClaimNames"},"trustedProviderEmail":{"type":"boolean"},"provisioning":{"type":"string","enum":["auto_create","pre_provisioned_only"],"description":"`auto_create` creates a board account on first sign-in; `pre_provisioned_only` signs in only people who already have one."},"offeredToCandidates":{"type":"boolean","description":"Whether candidates can sign in with this connection."},"offeredToEmployers":{"type":"boolean","description":"Whether employers can sign in with this connection."},"liveConfigTested":{"type":"boolean","description":"A test passed on the live settings, so the connection can be switched on. Until then both switches stay off."},"pendingChanges":{"$ref":"#/components/schemas/SsoConnectionPendingChanges"},"callbackUrl":{"type":"string","description":"The redirect URL to register at the provider."},"lastTestPassedAt":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","object","protocol","label","provider","issuer","status","candidateSignInMode","employerSignInMode","discoveryUrl","authorizationEndpoint","tokenEndpoint","userinfoEndpoint","jwksUri","scopes","clientId","hasClientSecret","claimNames","trustedProviderEmail","provisioning","offeredToCandidates","offeredToEmployers","liveConfigTested","pendingChanges","callbackUrl","lastTestPassedAt","createdAt","updatedAt"]},"SsoConnectionClaimNames":{"type":"object","nullable":true,"properties":{"subject":{"type":"string","nullable":true,"maxLength":128,"description":"Claim holding the stable member ID. Defaults to `sub`."},"email":{"type":"string","nullable":true,"maxLength":128,"description":"Claim holding the email. Defaults to `email`."},"emailVerified":{"type":"string","nullable":true,"maxLength":128,"description":"Claim saying whether the email is verified. Defaults to `email_verified`."},"displayName":{"type":"string","nullable":true,"maxLength":128,"description":"Claim holding the display name. Defaults to `name`."}},"additionalProperties":false},"SsoConnectionPendingChanges":{"type":"object","nullable":true,"properties":{"protocol":{"type":"string","enum":["oidc","oauth2_userinfo"],"description":"`oidc` for OpenID Connect providers (discovery and ID tokens); `oauth2_userinfo` for OAuth 2.0 providers that expose a userinfo endpoint instead."},"issuer":{"type":"string"},"discoveryUrl":{"type":"string","nullable":true},"authorizationEndpoint":{"type":"string","nullable":true},"tokenEndpoint":{"type":"string","nullable":true},"userinfoEndpoint":{"type":"string","nullable":true},"jwksUri":{"type":"string","nullable":true},"scopes":{"type":"array","nullable":true,"items":{"type":"string"}},"clientId":{"type":"string"},"hasClientSecret":{"type":"boolean"},"claimNames":{"$ref":"#/components/schemas/SsoConnectionClaimNames"}},"required":["protocol","issuer","discoveryUrl","authorizationEndpoint","tokenEndpoint","userinfoEndpoint","jwksUri","scopes","clientId","hasClientSecret","claimNames"],"description":"Settings edits on a tested connection wait here until a test passes on them and they are saved in the dashboard; sign-ins keep using the live settings meanwhile."},"CreateSsoConnectionBody":{"type":"object","properties":{"protocol":{"type":"string","enum":["oidc","oauth2_userinfo"],"description":"`oidc` for OpenID Connect providers (discovery and ID tokens); `oauth2_userinfo` for OAuth 2.0 providers that expose a userinfo endpoint instead."},"issuer":{"type":"string","minLength":1,"maxLength":2048,"description":"The provider issuer URL. Every sign-in must come from this issuer; it identifies linked identities. May be left out to create a draft, which cannot be tested until it is set."},"discoveryUrl":{"type":"string","nullable":true,"minLength":1,"maxLength":2048,"description":"OpenID Connect discovery URL. Defaults to `{issuer}/.well-known/openid-configuration`."},"authorizationEndpoint":{"type":"string","nullable":true,"minLength":1,"maxLength":2048,"description":"Authorization URL. Required for `oauth2_userinfo`."},"tokenEndpoint":{"type":"string","nullable":true,"minLength":1,"maxLength":2048,"description":"Token URL. Required for `oauth2_userinfo`."},"userinfoEndpoint":{"type":"string","nullable":true,"minLength":1,"maxLength":2048,"description":"Userinfo URL. Required for `oauth2_userinfo`."},"jwksUri":{"type":"string","nullable":true,"minLength":1,"maxLength":2048,"description":"JWKS URL, when the discovery document does not name one."},"scopes":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":128},"maxItems":20,"description":"Scopes requested from the provider."},"clientId":{"type":"string","minLength":1,"maxLength":2048,"description":"The client ID registered at the provider. May be left out to create a draft, which cannot be tested until it is set."},"clientSecret":{"type":"string","nullable":true,"minLength":1,"maxLength":2048,"description":"The client secret. Write-only: stored encrypted and never returned. On update, omit it to keep the stored secret or send `null` to remove it."},"claimNames":{"type":"object","nullable":true,"properties":{"subject":{"type":"string","nullable":true,"maxLength":128,"description":"Claim holding the stable member ID. Defaults to `sub`."},"email":{"type":"string","nullable":true,"maxLength":128,"description":"Claim holding the email. Defaults to `email`."},"emailVerified":{"type":"string","nullable":true,"maxLength":128,"description":"Claim saying whether the email is verified. Defaults to `email_verified`."},"displayName":{"type":"string","nullable":true,"maxLength":128,"description":"Claim holding the display name. Defaults to `name`."}},"additionalProperties":false,"description":"Where to read identity from in the provider response."},"label":{"type":"string","minLength":1,"maxLength":80,"description":"The text on the sign-in button."},"provider":{"type":"string","enum":["okta","generic_oidc","generic_oauth2"],"description":"The identity provider the connection is for: `okta`, or `generic_oidc` / `generic_oauth2` for any other provider that supports OpenID Connect or OAuth 2.0. Only used to name the provider in the dashboard’s setup steps; it does not change how sign-in works."},"trustedProviderEmail":{"type":"boolean","description":"Sign someone straight into the existing board account with the same verified email, without a confirmation email. Only enable when the provider alone controls who has each email."},"provisioning":{"type":"string","enum":["auto_create","pre_provisioned_only"],"description":"`auto_create` creates a board account on first sign-in; `pre_provisioned_only` signs in only people who already have one."},"candidateSignInMode":{"type":"string","enum":["off","available","required"],"description":"Deprecated: use per-role connection switches and settings.signInMethods instead."},"employerSignInMode":{"type":"string","enum":["off","available","required"],"description":"Deprecated: use per-role connection switches and settings.signInMethods instead."}},"required":["protocol","label"],"additionalProperties":false},"UpdateSsoConnectionBody":{"type":"object","properties":{"protocol":{"type":"string","enum":["oidc","oauth2_userinfo"],"description":"`oidc` for OpenID Connect providers (discovery and ID tokens); `oauth2_userinfo` for OAuth 2.0 providers that expose a userinfo endpoint instead."},"issuer":{"type":"string","minLength":1,"maxLength":2048,"description":"The provider issuer URL. Every sign-in must come from this issuer; it identifies linked identities."},"discoveryUrl":{"type":"string","nullable":true,"minLength":1,"maxLength":2048,"description":"OpenID Connect discovery URL. Defaults to `{issuer}/.well-known/openid-configuration`."},"authorizationEndpoint":{"type":"string","nullable":true,"minLength":1,"maxLength":2048,"description":"Authorization URL. Required for `oauth2_userinfo`."},"tokenEndpoint":{"type":"string","nullable":true,"minLength":1,"maxLength":2048,"description":"Token URL. Required for `oauth2_userinfo`."},"userinfoEndpoint":{"type":"string","nullable":true,"minLength":1,"maxLength":2048,"description":"Userinfo URL. Required for `oauth2_userinfo`."},"jwksUri":{"type":"string","nullable":true,"minLength":1,"maxLength":2048,"description":"JWKS URL, when the discovery document does not name one."},"scopes":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":128},"maxItems":20,"description":"Scopes requested from the provider."},"clientId":{"type":"string","minLength":1,"maxLength":2048,"description":"The client ID registered at the provider."},"clientSecret":{"type":"string","nullable":true,"minLength":1,"maxLength":2048,"description":"The client secret. Write-only: stored encrypted and never returned. On update, omit it to keep the stored secret or send `null` to remove it."},"claimNames":{"type":"object","nullable":true,"properties":{"subject":{"type":"string","nullable":true,"maxLength":128,"description":"Claim holding the stable member ID. Defaults to `sub`."},"email":{"type":"string","nullable":true,"maxLength":128,"description":"Claim holding the email. Defaults to `email`."},"emailVerified":{"type":"string","nullable":true,"maxLength":128,"description":"Claim saying whether the email is verified. Defaults to `email_verified`."},"displayName":{"type":"string","nullable":true,"maxLength":128,"description":"Claim holding the display name. Defaults to `name`."}},"additionalProperties":false,"description":"Where to read identity from in the provider response."},"label":{"type":"string","minLength":1,"maxLength":80,"description":"The text on the sign-in button."},"provider":{"type":"string","enum":["okta","generic_oidc","generic_oauth2"],"description":"The identity provider the connection is for: `okta`, or `generic_oidc` / `generic_oauth2` for any other provider that supports OpenID Connect or OAuth 2.0. Only used to name the provider in the dashboard’s setup steps; it does not change how sign-in works."},"trustedProviderEmail":{"type":"boolean","description":"Sign someone straight into the existing board account with the same verified email, without a confirmation email. Only enable when the provider alone controls who has each email."},"provisioning":{"type":"string","enum":["auto_create","pre_provisioned_only"],"description":"`auto_create` creates a board account on first sign-in; `pre_provisioned_only` signs in only people who already have one."},"candidateSignInMode":{"type":"string","enum":["off","available","required"],"description":"Deprecated: use per-role connection switches and settings.signInMethods instead."},"employerSignInMode":{"type":"string","enum":["off","available","required"],"description":"Deprecated: use per-role connection switches and settings.signInMethods instead."},"offeredToCandidates":{"type":"boolean","description":"Switch the connection on or off for candidates. Switching on needs a passing test on the live settings (409 `sso_connections_untested`); switching off is refused while it is the only way candidates can sign in (409 `sign_in_method_last`)."},"offeredToEmployers":{"type":"boolean","description":"Switch the connection on or off for employers, with the same rules as `offeredToCandidates`."}},"additionalProperties":false},"SsoConnectionTestResult":{"type":"object","properties":{"object":{"type":"string","enum":["sso_connection_test_result"]},"testId":{"type":"string"},"passed":{"type":"boolean"},"configSource":{"type":"string","enum":["live","pending"],"description":"Whether the test ran on the live settings or on pending changes."},"outcome":{"type":"string","enum":["recorded","promoted","stale_config"],"description":"`stale_config`: settings changed during the test, so it does not count. `promoted` appears only on results recorded before saving took over making pending changes live."},"principal":{"type":"object","nullable":true,"properties":{"issuer":{"type":"string"},"subject":{"type":"string"},"email":{"type":"string","nullable":true},"emailVerified":{"type":"boolean"},"displayName":{"type":"string","nullable":true}},"required":["issuer","subject","email","emailVerified","displayName"]},"claims":{"type":"object","nullable":true,"additionalProperties":{"nullable":true},"description":"The claims the provider sent, bounded in size."},"warnings":{"type":"array","items":{"type":"string"}},"error":{"type":"object","nullable":true,"properties":{"code":{"type":"string"},"message":{"type":"string"},"expected":{"type":"string","nullable":true},"received":{"type":"string","nullable":true}},"required":["code","message","expected","received"]},"completedAt":{"type":"string"},"expiresAt":{"type":"string"}},"required":["object","testId","passed","configSource","outcome","principal","claims","warnings","error","completedAt","expiresAt"]},"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"]},"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},"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","service"]},"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"]},"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["webhook_delivery"]},"event_id":{"type":"string","description":"Stable public event id (e.g. evt_…). Unchanged across retries and replay."},"event_type":{"type":"string"},"endpoint_id":{"type":"string"},"status":{"type":"string","enum":["pending","retrying","delivered","terminal","exhausted"]},"terminal_reason":{"type":"string","nullable":true,"enum":["http_410","permanent_response","invalid_reference","endpoint_paused","retry_attempt_limit","delivery_window_expired","retention_expired","endpoint_retired"]},"replayable":{"type":"boolean"},"replay_expires_at":{"type":"string"},"payload_purged_at":{"type":"string","nullable":true},"attempt_count":{"type":"integer"},"next_attempt_at":{"type":"string","nullable":true},"first_attempt_at":{"type":"string","nullable":true},"last_attempt_at":{"type":"string","nullable":true},"completed_at":{"type":"string","nullable":true},"created_at":{"type":"string"}},"required":["id","object","event_id","event_type","endpoint_id","status","terminal_reason","replayable","replay_expires_at","payload_purged_at","attempt_count","next_attempt_at","first_attempt_at","last_attempt_at","completed_at","created_at"]},"WebhookDeliveryDetail":{"allOf":[{"$ref":"#/components/schemas/WebhookDelivery"},{"type":"object","properties":{"attempts":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDeliveryAttempt"}}},"required":["attempts"]}]},"WebhookDeliveryAttempt":{"type":"object","properties":{"attempt_number":{"type":"integer"},"started_at":{"type":"string"},"duration_ms":{"type":"integer"},"outcome":{"type":"string","enum":["delivered","retryable","terminal"]},"status_code":{"type":"integer","nullable":true},"status_class":{"type":"string"},"diagnostic":{"type":"string","description":"Sanitized diagnostic recorded at attempt time. Never a response body or secret."}},"required":["attempt_number","started_at","duration_ms","outcome","status_code","status_class","diagnostic"]},"AnalyticsJobApplyClick":{"type":"object","properties":{"object":{"type":"string","enum":["analytics_job_apply_click"]},"jobId":{"type":"string","description":"Job document id (`job_apply_click.job_id`). Join to jobs export `id`."},"companySlug":{"type":"string","description":"Company slug from the apply-click payload. Empty if absent."},"jobSlug":{"type":"string","description":"Job slug at click time (`job_apply_click.job_slug`), or the current slug from the one-shot historical map. Empty when neither is known. Join to jobs export `slug` with `companySlug`."},"channel":{"type":"string","description":"First-touch channel for the session (same keys as Home Channel)."},"applyClicks":{"type":"integer","description":"Apply-click events for this job × channel in the range."}},"required":["object","jobId","companySlug","jobSlug","channel","applyClicks"]},"AnalyticsJobVisitor":{"type":"object","properties":{"object":{"type":"string","enum":["analytics_job_visitor"]},"companySlug":{"type":"string","description":"Company slug from the job-detail path."},"jobSlug":{"type":"string","description":"Frozen job slug from `/companies/{companySlug}/jobs/{jobSlug}`. Join with jobs export `company_slug` + `slug` (not `id`). A deliberate slug rename splits history."},"channel":{"type":"string","description":"First-touch channel for the session (same keys as Home Channel)."},"campaign":{"type":"string","description":"utm_campaign from the first-touch href. Empty when the landing URL was untagged."},"utmSource":{"type":"string","description":"utm_source from the first-touch href. Empty when untagged."},"utmMedium":{"type":"string","description":"utm_medium from the first-touch href. Empty when untagged."},"visitors":{"type":"integer","description":"Unique sessions that viewed this job-detail page, attributed to that first-touch. Always lower than jobs-export `views` (page hits); the two are not expected to match."}},"required":["object","companySlug","jobSlug","channel","campaign","utmSource","utmMedium","visitors"]},"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"]},"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"]},"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"]},"SearchConsoleInspectionResponse":{"type":"object","properties":{"object":{"type":"string","enum":["search_console_url_inspection"]},"inspectionResult":{"type":"object","properties":{"inspectionResultLink":{"type":"string"},"indexStatusResult":{"type":"object","properties":{"verdict":{"type":"string"},"coverageState":{"type":"string"},"lastCrawlTime":{"type":"string"},"pageFetchState":{"type":"string"},"robotsTxtState":{"type":"string"},"indexingState":{"type":"string"},"googleCanonical":{"type":"string"},"userCanonical":{"type":"string"},"crawledAs":{"type":"string"},"sitemap":{"type":"array","items":{"type":"string"}},"referringUrls":{"type":"array","items":{"type":"string"}}}},"richResultsResult":{"type":"object","additionalProperties":{"nullable":true}},"ampResult":{"type":"object","additionalProperties":{"nullable":true}},"mobileUsabilityResult":{"type":"object","additionalProperties":{"nullable":true}}}},"cavuno":{"type":"object","properties":{"coverage":{"type":"object","properties":{"mode":{"type":"string","enum":["board_hosts","whole_property"]},"hostnames":{"type":"array","items":{"type":"string"}}},"required":["mode","hostnames"]},"indexedVersionOnly":{"type":"boolean","enum":[true]}},"required":["coverage","indexedVersionOnly"]}},"required":["object","cavuno"]},"SearchConsoleQueryResponse":{"type":"object","properties":{"object":{"type":"string","enum":["search_console_query"]},"rows":{"type":"array","items":{"type":"object","properties":{"keys":{"type":"array","items":{"type":"string"}},"clicks":{"type":"number"},"impressions":{"type":"number"},"ctr":{"type":"number"},"position":{"type":"number"}}}},"responseAggregationType":{"type":"string"},"metadata":{"type":"object","additionalProperties":{"nullable":true}},"cavuno":{"type":"object","properties":{"coverage":{"type":"object","properties":{"mode":{"type":"string","enum":["board_hosts","whole_property"]},"hostnames":{"type":"array","items":{"type":"string"}}},"required":["mode","hostnames"]},"dataState":{"type":"string","enum":["final"]},"dataTimezone":{"type":"string","enum":["America/Los_Angeles"]},"latestObservedDate":{"type":"string"},"exhaustive":{"type":"boolean","enum":[false]}},"required":["coverage","dataState","dataTimezone","exhaustive"]}},"required":["object","rows","cavuno"]},"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"}},"campaigns":{"type":"array","items":{"$ref":"#/components/schemas/AnalyticsTrafficCampaign"}}},"required":["object","range","pages","sources","locations","devices","campaigns"]},"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"]},"AnalyticsTrafficCampaign":{"type":"object","properties":{"campaign":{"type":"string","description":"utm_campaign from the session first-touch href."},"source":{"type":"string","description":"utm_source from the session first-touch href."},"medium":{"type":"string","description":"utm_medium from the session first-touch href."},"content":{"type":"string","description":"utm_content from the session first-touch href, '' when untagged. Only with `campaignGroupBy=content`."},"term":{"type":"string","description":"utm_term from the session first-touch href, '' when untagged. Only with `campaignGroupBy=content`."},"visits":{"type":"number"},"visitsChangePercentage":{"type":"number","nullable":true},"applyClicks":{"type":"number"}},"required":["campaign","source","medium","visits","visitsChangePercentage","applyClicks"]},"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"]},"BackfillMatchCandidate":{"type":"object","properties":{"index":{"type":"integer","minimum":0},"name":{"type":"string"},"website":{"type":"string","nullable":true}},"required":["index","name","website"]},"BackfillBulkResult":{"type":"object","properties":{"object":{"type":"string","enum":["backfill_bulk_result"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/BackfillBulkItemResult"}}},"required":["object","data"]},"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"]},"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},"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},"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}},"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}},"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},"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","scale","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"]},"BillingHostedCheckoutFunding":{"type":"object","properties":{"type":{"type":"string","enum":["hosted_checkout"]}},"required":["type"]},"BillingCheckoutBody":{"type":"object","properties":{"planKey":{"type":"string","enum":["starter","basic","grow","advanced","scale","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","scale","enterprise"],"description":"Self-serve plan key. enterprise is not self-serve and returns plan_not_self_serve."}},"required":["object","funding","status","url","planKey"]},"BillingUpgradeBody":{"type":"object","properties":{"planKey":{"type":"string","enum":["starter","basic","grow","advanced","scale","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"]},"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."},"location":{"type":"string","nullable":true,"description":"The author's free-text location label, 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."},"facebookUrl":{"type":"string","nullable":true,"description":"The author's Facebook 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","location","status","avatarUrl","websiteUrl","facebookUrl","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."},"location":{"type":"string","maxLength":200,"description":"Free-text location label for the author (e.g. `Sydney, Australia`)."},"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."},"facebookUrl":{"type":"string","maxLength":500,"description":"The author's Facebook profile URL."},"twitterUrl":{"type":"string","maxLength":500,"description":"The author's X (Twitter) profile URL. Stored as the canonical `https://x.com/<handle>` 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},"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","nullable":true,"maxLength":320,"format":"email","description":"The author's email address. Pass `null` to clear the stored value; omitted means unchanged."},"location":{"type":"string","maxLength":200,"description":"Free-text location label for the author (e.g. `Sydney, Australia`)."},"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","nullable":true,"maxLength":500,"description":"The author's personal website URL. Normalized to a canonical URL when stored. Pass `null` or `\"\"` to clear the stored value; omitted means unchanged."},"facebookUrl":{"type":"string","nullable":true,"maxLength":500,"description":"The author's Facebook profile URL. Pass `null` or `\"\"` to clear the stored value; omitted means unchanged."},"twitterUrl":{"type":"string","nullable":true,"maxLength":500,"description":"The author's X (Twitter) profile URL. Stored as the canonical `https://x.com/<handle>` URL. Pass `null` or `\"\"` to clear the stored value; omitted means unchanged."},"linkedinUrl":{"type":"string","nullable":true,"maxLength":500,"description":"The author's LinkedIn profile URL. Pass `null` or `\"\"` to clear the stored value; omitted means unchanged."},"githubUrl":{"type":"string","nullable":true,"maxLength":500,"description":"The author's GitHub profile URL. Pass `null` or `\"\"` to clear the stored value; omitted means unchanged."},"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"]},"BlogPost":{"allOf":[{"$ref":"#/components/schemas/BlogPostSummary"},{"type":"object","properties":{"html":{"type":"string","nullable":true}},"required":["html"]}]},"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},"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","nullable":true,"maxLength":500,"description":"Canonical URL for the post. Pass `null` or `\"\"` to clear the stored value; omitted means unchanged."},"publishedAt":{"type":"string","format":"date-time"},"title":{"type":"string","minLength":1,"maxLength":200},"status":{"type":"string","enum":["draft","scheduled","published"]}},"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},"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},"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},"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},"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,"maxLength":40},"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},"RenameCouponBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":40}},"required":["name"],"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"]},"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},"DevelopmentOrigin":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["development_origin"]},"origin":{"type":"string","description":"Normalized origin, or `https://*.<domain>` for a wildcard entry."},"kind":{"type":"string","enum":["loopback","https","wildcard"],"description":"`loopback` for localhost addresses, `https` for one exact origin, `wildcard` for one subdomain level under a verified domain."},"createdAt":{"type":"string"}},"required":["id","object","origin","kind","createdAt"]},"CreateDevelopmentOriginBody":{"type":"object","properties":{"origin":{"type":"string","minLength":1,"maxLength":300,"description":"Where sign-in may complete while you test a self-hosted frontend: `http://localhost:<port>` (or `127.0.0.1` / `[::1]`), one exact `https://` origin such as a preview deployment, or `https://*.<domain>` under a domain verified on this board. Wildcards on shared hosting suffixes such as `vercel.app` are refused; register each preview URL instead."}},"required":["origin"],"additionalProperties":false},"CustomObjectType":{"type":"object","properties":{"id":{"type":"string","minLength":1},"object":{"type":"string","enum":["custom_object_type"]},"name":{"type":"string"},"key":{"type":"string"},"definitions":{"type":"array","items":{"anyOf":[{"$ref":"#/components/schemas/ScalarProfileCustomFieldDefinition"},{"$ref":"#/components/schemas/CollectionMediaFieldDefinition"}]}},"archived":{"type":"boolean"},"logoFieldKey":{"type":"string","nullable":true,"description":"Key of the Image field whose image is each record's logo, or null when the type has no logo field."},"createdAt":{"type":"string","format":"date-time"}},"required":["id","object","name","key","definitions","archived","logoFieldKey","createdAt"]},"CollectionMediaFieldDefinition":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"type":{"type":"string","enum":["image","image_gallery","file"]},"required":{"type":"boolean"},"visibility":{"type":"string","enum":["private","public"]},"editableByOwner":{"type":"boolean","enum":[false]},"helpText":{"type":"string","maxLength":500}},"required":["key","label","type","required","visibility","editableByOwner"],"additionalProperties":false},"StartCustomObjectRecordsImportBody":{"type":"object","properties":{"records":{"type":"array","items":{"$ref":"#/components/schemas/CreateCustomObjectRecordBody"}}},"required":["records"],"additionalProperties":false},"CreateCustomObjectRecordBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":160},"logoUrl":{"type":"string","maxLength":2000,"format":"uri","description":"Deprecated: use the collection's logo image field (`logoFieldKey` on the type). A legacy logo URL stored on older records."},"externalId":{"type":"string","minLength":1,"maxLength":200},"values":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}}]}}},"required":["name","values"],"additionalProperties":false},"CreateCustomObjectTypeBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"key":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_-]{0,63}$"},"definitions":{"type":"array","items":{"anyOf":[{"$ref":"#/components/schemas/ScalarProfileCustomFieldDefinition"},{"$ref":"#/components/schemas/CollectionMediaFieldDefinition"}]}},"logoFieldKey":{"type":"string","description":"Key of one of the `image` definitions to use as the logo."}},"required":["name","key","definitions"],"additionalProperties":false},"UpdateCustomObjectTypeBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"definitions":{"type":"array","items":{"anyOf":[{"$ref":"#/components/schemas/ScalarProfileCustomFieldDefinition"},{"$ref":"#/components/schemas/CollectionMediaFieldDefinition"}]}},"archived":{"type":"boolean"},"logoFieldKey":{"type":"string","nullable":true,"description":"Key of one of the `image` definitions to use as the logo; null clears it. Removing that definition clears it too."}},"additionalProperties":false},"CustomObjectRecord":{"type":"object","properties":{"id":{"type":"string","minLength":1},"object":{"type":"string","enum":["custom_object_record"]},"typeId":{"type":"string","minLength":1},"name":{"type":"string"},"slug":{"type":"string","nullable":true,"description":"URL-safe identifier, unique within the collection. Changing it keeps the previous value reserved. Generated from the name on create; renaming keeps it. Null only on records saved before slugs existed."},"logoUrl":{"type":"string","nullable":true,"format":"uri","description":"Deprecated: use the collection's logo image field (`logoFieldKey` on the type). A legacy logo URL stored on older records."},"externalId":{"type":"string","nullable":true},"values":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}}]}},"archived":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","object","typeId","name","slug","logoUrl","externalId","values","archived","createdAt"]},"CustomObjectImportResult":{"type":"object","properties":{"created":{"type":"integer","minimum":0},"updated":{"type":"integer","minimum":0}},"required":["created","updated"]},"ImportCustomObjectRecordsBody":{"type":"object","properties":{"records":{"type":"array","items":{"$ref":"#/components/schemas/CreateCustomObjectRecordBody"},"maxItems":500}},"required":["records"],"additionalProperties":false},"UpdateCustomObjectRecordBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":160},"slug":{"type":"string","minLength":1,"maxLength":80,"description":"URL-safe identifier, unique within the collection. Changing it keeps the previous value reserved. Lowercase letters, numbers and single hyphens. Another record's current or previous slug is rejected with 400."},"logoUrl":{"type":"string","nullable":true,"maxLength":2000,"format":"uri","description":"Deprecated: use the collection's logo image field (`logoFieldKey` on the type). A legacy logo URL stored on older records."},"externalId":{"type":"string","nullable":true,"minLength":1,"maxLength":200},"values":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}}]}},"archived":{"type":"boolean"}},"additionalProperties":false},"EmailDomain":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["email_domain"]},"domain":{"type":"string","description":"The sending hostname."},"status":{"type":"string","enum":["pending","verified","failed"],"description":"`pending` until the required DNS records verify, `verified` once board email sends from this domain, `failed` when the last check found a problem (see `statusReason`; publish or fix the records and verify again)."},"senderName":{"type":"string"},"senderLocalPart":{"type":"string"},"senderAddress":{"type":"string","description":"The From address once the domain is verified."},"dnsRecords":{"type":"array","items":{"$ref":"#/components/schemas/EmailDomainDnsRecord"},"description":"Records to publish at the domain’s DNS provider. Empty while the domain is still being set up with the email provider; call verify to retry."},"statusReason":{"type":"string","nullable":true,"enum":["setup_required","dns_verification_failed"],"description":"Why the last check failed, when it did. `setup_required`: the domain must be set up with the email provider again; call verify, which re-stages it and returns fresh DNS records. `dns_verification_failed`: the published records do not match yet; check each record’s `status`, fix them and verify again."},"verifiedAt":{"type":"string","nullable":true},"lastCheckedAt":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","object","domain","status","senderName","senderLocalPart","senderAddress","dnsRecords","statusReason","verifiedAt","lastCheckedAt","createdAt"]},"EmailDomainDnsRecord":{"type":"object","properties":{"purpose":{"type":"string","enum":["dkim","return_path","dmarc"],"description":"`dkim` signs outgoing mail, `return_path` receives bounces and complaints, `dmarc` is an optional policy record."},"type":{"type":"string","description":"DNS record type, for example `CNAME` or `TXT`."},"name":{"type":"string","description":"Host to create the record on, relative to the DNS zone the domain lives in (`@` is the zone itself), as most DNS providers expect it typed."},"value":{"type":"string","description":"Exact value to publish."},"ttl":{"type":"string","description":"Suggested TTL. `Auto` means the DNS provider’s default."},"required":{"type":"boolean","description":"Whether the domain needs this record to send. DMARC is recommended but optional."},"status":{"type":"string","description":"Last check of this record: `pending`, `verified`, or `failed`."}},"required":["purpose","type","name","value","ttl","required","status"]},"CreateEmailDomainBody":{"type":"object","properties":{"domain":{"type":"string","minLength":1,"maxLength":253,"description":"Hostname to send from. It must be the board’s active primary custom domain or one of its subdomains; a subdomain such as `notifications.acme.com` is recommended so the main domain’s email reputation stays separate. Normalized to lowercase."},"senderName":{"type":"string","minLength":1,"maxLength":200,"description":"Display name recipients see in the From header, for example `Acme Jobs`. Defaults to the board name."},"senderLocalPart":{"type":"string","minLength":1,"maxLength":64,"description":"Mailbox before the `@`, for example `info` or `hello`. Defaults to `info`. Normalized to lowercase."}},"required":["domain"],"additionalProperties":false},"UpdateEmailDomainBody":{"type":"object","properties":{"senderName":{"type":"string","minLength":1,"maxLength":200,"description":"Display name recipients see in the From header."},"senderLocalPart":{"type":"string","minLength":1,"maxLength":64,"description":"Mailbox before the `@`. Normalized to lowercase."}},"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"]},"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"]},"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"]},"DomainVerificationInstructions":{"type":"object","properties":{"method":{"type":"string","enum":["txt"]},"name":{"type":"string"},"expectedValue":{"type":"string","nullable":true}},"required":["method","name","expectedValue"]},"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},"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"]},"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,"description":"ISO-8601 timestamp of the last activity on the board (a sign-in or signed-in use), to the hour, or `null`."},"deactivatedAt":{"type":"string","nullable":true,"format":"date-time","description":"ISO 8601 timestamp when sign-in was disabled, or `null` when the employer can sign in. Deactivate revokes all sessions and blocks sign-in; company memberships, claims, and jobs are preserved. Reactivate restores sign-in; the employer signs in again to establish a new session."},"companies":{"type":"array","items":{"$ref":"#/components/schemas/EmployerApprovedCompany"},"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","deactivatedAt","companies","pendingClaims"]},"EmployerApprovedCompany":{"type":"object","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"]},"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"]},"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"]},"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},"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"]},"ImportBatchError":{"type":"object","properties":{"rowIndex":{"type":"number"},"code":{"type":"string"},"message":{"type":"string"}},"required":["rowIndex","code","message"]},"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"]},"IndexingConfig":{"type":"object","properties":{"id":{"type":"string","enum":["indexing_config"]},"object":{"type":"string","enum":["indexing_config"]},"enabled":{"type":"boolean","description":"Whether the Google Indexing API is enabled: Google is notified immediately when jobs are published or removed. Your site is indexed by Google either way. `true` means setup is complete: Cavuno only enables it after Google confirms the service account is an Owner of the Search Console property, so there is nothing left to add or verify. Use `lastRunAt` and `lastError` to check that submissions keep succeeding."},"indexNowEnabled":{"type":"boolean","description":"Whether IndexNow (Bing/Yandex) instant indexing is enabled."},"provisioningStatus":{"type":"string","nullable":true,"description":"Provisioning state of the board's Google Cloud project for the Google Indexing API (`pending` | `provisioning` | `ready` | `error`), or null when setup has not started."},"lastRunAt":{"type":"string","nullable":true,"description":"ISO-8601 timestamp of the last successful Google Indexing API submission, or null. Submissions are sent when jobs are published or removed, so it stays null until the first one succeeds after indexing is enabled."},"lastError":{"type":"string","nullable":true,"description":"The last recorded Google Indexing API 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. `tinybird` is deprecated: first-party Board analytics need no connection and are served live by the `/v1/analytics` endpoints, so connecting it changes nothing."},"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"]},"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"]},"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"]}]},"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"]},"JobFeed":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["job_feed"]},"name":{"type":"string"},"url":{"type":"string"},"status":{"type":"string","enum":["pending_mapping","active","failing","needs_review"],"description":"`pending_mapping`: the first run (or a re-detection) has not produced a mapping yet. `failing`: recent runs failed (see `lastError`). `needs_review`: runs are held until the mapping is fixed or re-detected."},"enabled":{"type":"boolean"},"intervalHours":{"type":"number"},"expireMissing":{"type":"boolean"},"jobLimit":{"type":"number","nullable":true},"applyUrlAttribution":{"$ref":"#/components/schemas/JobFeedApplyUrlAttribution"},"lastRunAt":{"type":"string","nullable":true},"nextRunAt":{"type":"string","nullable":true,"description":"When the next pull is due. `null` while the feed is disabled."},"lastError":{"type":"string","nullable":true},"consecutiveFailures":{"type":"number"},"createdAt":{"type":"string"}},"required":["id","object","name","url","status","enabled","intervalHours","expireMissing","jobLimit","applyUrlAttribution","lastRunAt","nextRunAt","lastError","consecutiveFailures","createdAt"]},"JobFeedApplyUrlAttribution":{"oneOf":[{"type":"object","properties":{"mode":{"type":"string","enum":["inherit"]}},"required":["mode"],"additionalProperties":false},{"type":"object","properties":{"mode":{"type":"string","enum":["off"]}},"required":["mode"],"additionalProperties":false},{"type":"object","properties":{"mode":{"type":"string","enum":["append"]},"params":{"type":"array","items":{"$ref":"#/components/schemas/ApplyUrlParamTemplate"},"maxItems":8}},"required":["mode","params"],"additionalProperties":false}],"description":"Outbound apply-URL attribution for this feed's jobs. `inherit` uses the Board setting."},"JobFeedDetail":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["job_feed"]},"name":{"type":"string"},"url":{"type":"string"},"status":{"type":"string","enum":["pending_mapping","active","failing","needs_review"],"description":"`pending_mapping`: the first run (or a re-detection) has not produced a mapping yet. `failing`: recent runs failed (see `lastError`). `needs_review`: runs are held until the mapping is fixed or re-detected."},"enabled":{"type":"boolean"},"intervalHours":{"type":"number"},"expireMissing":{"type":"boolean"},"jobLimit":{"type":"number","nullable":true},"applyUrlAttribution":{"$ref":"#/components/schemas/JobFeedApplyUrlAttribution"},"lastRunAt":{"type":"string","nullable":true},"nextRunAt":{"type":"string","nullable":true,"description":"When the next pull is due. `null` while the feed is disabled."},"lastError":{"type":"string","nullable":true},"consecutiveFailures":{"type":"number"},"createdAt":{"type":"string"},"mapping":{"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"]}},"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"]}},"defaults":{"type":"object","properties":{"employmentType":{"type":"string"},"remoteOption":{"type":"string"},"currency":{"type":"string"},"descriptionFormat":{"type":"string"}}},"fieldsNeedingReview":{"type":"array","items":{"type":"string"},"description":"Job fields whose detected mapping should be checked."},"sourceColumns":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"samples":{"type":"array","items":{"type":"string"}}},"required":["name","samples"]},"description":"Columns seen in the feed, with a few sample values."}},"required":["fieldMappings","valueTransforms","defaults","fieldsNeedingReview","sourceColumns"],"description":"Typed, operator-reviewable mapping. `null` until the first run (or a re-detection) has detected one."}},"required":["id","object","name","url","status","enabled","intervalHours","expireMissing","jobLimit","applyUrlAttribution","lastRunAt","nextRunAt","lastError","consecutiveFailures","createdAt","mapping"]},"CreateJobFeedBody":{"type":"object","properties":{"url":{"type":"string","minLength":1,"maxLength":2048,"format":"uri","description":"The XML feed URL. Checked before it is saved: Cavuno fetches it once and refuses a blocked, unreachable or non-XML URL."},"name":{"type":"string","minLength":1,"maxLength":80,"description":"Display name. Defaults to a name derived from the URL host."},"intervalHours":{"anyOf":[{"type":"number","enum":[1]},{"type":"number","enum":[3]},{"type":"number","enum":[6]},{"type":"number","enum":[12]},{"type":"number","enum":[24]}],"default":6,"description":"Hours between pulls."},"expireMissing":{"type":"boolean","default":true,"description":"Expire a job once it is missing from two successful runs in a row."},"jobLimit":{"type":"integer","nullable":true,"minimum":1,"maximum":100000,"default":null,"description":"Most jobs this feed may have published at once. `null` means no per-feed cap (plan and Board limits still apply)."}},"required":["url"],"additionalProperties":false},"UpdateJobFeedBody":{"type":"object","properties":{"url":{"type":"string","minLength":1,"maxLength":2048,"format":"uri","description":"The XML feed URL. Checked before it is saved: Cavuno fetches it once and refuses a blocked, unreachable or non-XML URL."},"name":{"type":"string","minLength":1,"maxLength":80},"intervalHours":{"anyOf":[{"type":"number","enum":[1]},{"type":"number","enum":[3]},{"type":"number","enum":[6]},{"type":"number","enum":[12]},{"type":"number","enum":[24]}],"description":"Hours between pulls."},"expireMissing":{"type":"boolean"},"enabled":{"type":"boolean","description":"A disabled feed is not pulled until it is enabled again."},"jobLimit":{"type":"integer","nullable":true,"minimum":1,"maximum":100000,"description":"Most jobs this feed may have published at once. `null` means no per-feed cap (plan and Board limits still apply)."},"applyUrlAttribution":{"$ref":"#/components/schemas/JobFeedApplyUrlAttribution"},"mapping":{"$ref":"#/components/schemas/JobFeedMappingInput"}},"additionalProperties":false},"JobFeedMappingInput":{"type":"object","properties":{"fieldMappings":{"type":"array","items":{"$ref":"#/components/schemas/JobFeedFieldMapping"},"maxItems":200},"valueTransforms":{"type":"array","items":{"$ref":"#/components/schemas/JobFeedValueTransform"},"maxItems":200,"default":[]}},"required":["fieldMappings"],"additionalProperties":false,"description":"Replaces the feed's column mappings and value transforms. Applies from the next run, which starts now."},"JobFeedFieldMapping":{"type":"object","properties":{"sourceColumn":{"type":"string","minLength":1,"maxLength":500},"targetField":{"type":"string","description":"A Cavuno job field, e.g. `title`, `company_name`, `description`, `apply_url`, `location_label`, `employment_type`."},"confidence":{"type":"number","minimum":0,"maximum":1},"notes":{"type":"string","maxLength":1000}},"required":["sourceColumn","targetField","confidence"],"additionalProperties":false},"JobFeedValueTransform":{"type":"object","properties":{"sourceColumn":{"type":"string","minLength":1,"maxLength":500},"targetField":{"type":"string","description":"A Cavuno job field, e.g. `title`, `company_name`, `description`, `apply_url`, `location_label`, `employment_type`."},"map":{"type":"object","additionalProperties":{"type":"string"},"description":"Source value → Cavuno value."},"fallback":{"type":"string"}},"required":["sourceColumn","targetField","map"],"additionalProperties":false},"JobFeedRun":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["job_feed_run"]},"status":{"type":"string"},"totalRows":{"type":"number"},"processedRows":{"type":"number"},"createdCount":{"type":"number"},"updatedCount":{"type":"number"},"skippedCount":{"type":"number"},"errorCount":{"type":"number"},"errors":{"type":"array","items":{"type":"object","properties":{"rowIndex":{"type":"number"},"code":{"type":"string"},"message":{"type":"string"}},"required":["rowIndex","code","message"]},"description":"The first 20 row errors; `errorCount` is the total."},"startedAt":{"type":"string","nullable":true},"completedAt":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","object","status","totalRows","processedRows","createdCount","updatedCount","skippedCount","errorCount","errors","startedAt","completedAt","createdAt"]},"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","pending_approval"],"description":"Current status of the job. One of `draft`, `published`, `expired`, `archived`, or `pending_approval`. A `pending_approval` job is waiting for an operator to approve it: approve with `POST /v1/jobs/:id/publish`, reject with `DELETE /v1/jobs/:id`. It is not public, like a draft."},"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. For a job with a custom employment type, this is the Google equivalent of the custom type."},"customEmploymentType":{"type":"object","nullable":true,"properties":{"key":{"type":"string","description":"Stable key of the custom employment type. Never changes."},"label":{"type":"string","description":"Display name of the custom employment type, as configured."}},"required":["key","label"],"description":"The board's custom employment type for this job (for example `Casual`), or `null` when the job uses a built-in type only. A deleted custom type reads back as `null` and the job shows its built-in `employmentType`."},"remoteOption":{"type":"string","nullable":true,"enum":["on_site","hybrid","remote"],"description":"Whether the role is on-site, hybrid, or fully remote. `null` only on older jobs saved without one; create requires it and `PATCH` cannot clear it."},"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 as an ISO 8601 datetime. `null` can appear when the expiry requirement does not apply, including for drafts and sponsored jobs; ordinary published jobs always have an expiry."},"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."},"revision":{"type":"integer","minimum":0,"description":"Monotonic Job lifecycle revision used to reconcile webhook events. Legacy rows are 0 until the rollout backfill runs."},"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."},"collectionValues":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"},"maxItems":100},"description":"Operator-facing collection record IDs keyed by job collection field. Always an object; values are arrays even for single-select fields."},"links":{"$ref":"#/components/schemas/AdminOnlyResourceLinks"}},"required":["id","object","title","slug","status","companyId","employmentType","customEmploymentType","remoteOption","seniority","salaryMin","salaryMax","salaryCurrency","salaryTimeframe","isFeatured","publishedAt","expiresAt","createdAt","updatedAt","revision","skills","categories","externalId","customFieldValues","collectionValues","links"]},"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."},"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."},"resolvedCollectionFields":{"type":"array","items":{"$ref":"#/components/schemas/ResolvedJobCollectionField"},"description":"Collection selections resolved to current live names, logos, and public record details."},"description":{"type":"string","nullable":true,"description":"Long-form description of the role (HTML), 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":["resolvedCollectionFields","description","applicationUrl","remotePermits","remoteWorldwide","remoteTimezones","remoteAllowedTzOffsets","remoteWorkPermitCountryCodes","remoteWorkPermitSubdivisionCodes","remoteSponsorship","educationRequirements","experienceMonths","experienceInPlaceOfEducation","inOfficePeriod","inOfficeFrequency","company","officeLocations"]}]},"ResolvedJobCollectionField":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"entries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string","description":"URL-safe identifier, unique within the collection. Changing it keeps the previous value reserved."},"logoUrl":{"type":"string","description":"The entry's logo: the image in the collection's logo field, or a legacy logo URL on older entries. Absent when the entry has neither."},"title":{"type":"string","description":"The entry's title on this job: the job's `titleOverride` when set, otherwise the entry name. Render this."},"description":{"type":"string","nullable":true,"description":"The entry's description on this job: the job's `descriptionOverride` when set, otherwise the value of the field's default description field, or `null` when neither exists. Sanitised HTML when the default description field is rich text, with a plain-text override escaped into paragraphs. Render this."},"titleOverride":{"type":"string","nullable":true,"description":"The title this job set for the entry, or `null` when it uses the entry name."},"descriptionOverride":{"type":"string","nullable":true,"description":"The plain-text description this job set for the entry, or `null` when it uses the default description."},"fields":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"type":{"type":"string","enum":["short_text","long_text","rich_text","single_select","multi_select","boolean","number","date","url","email","phone","image","image_gallery","file","reference"]},"helpText":{"type":"string"},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"}},"required":["key","label"]}}},"required":["key","label","type"]}},"values":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"boolean"},{"type":"number"},{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"contentType":{"type":"string"},"sizeBytes":{"type":"number"},"url":{"type":"string"}},"required":["id","name","contentType","sizeBytes","url"]},{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"contentType":{"type":"string"},"sizeBytes":{"type":"number"},"url":{"type":"string"}},"required":["id","name","contentType","sizeBytes","url"]}}]}},"references":{"type":"object","additionalProperties":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string","description":"URL-safe identifier, unique within the collection. Changing it keeps the previous value reserved."},"fields":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"type":{"type":"string","enum":["short_text","long_text","rich_text","single_select","multi_select","boolean","number","date","url","email","phone","image","image_gallery","file","reference"]},"helpText":{"type":"string"},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"}},"required":["key","label"]}}},"required":["key","label","type"]}},"values":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"boolean"},{"type":"number"},{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"contentType":{"type":"string"},"sizeBytes":{"type":"number"},"url":{"type":"string"}},"required":["id","name","contentType","sizeBytes","url"]},{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"contentType":{"type":"string"},"sizeBytes":{"type":"number"},"url":{"type":"string"}},"required":["id","name","contentType","sizeBytes","url"]}}]}}},"required":["id","name","fields","values"]}}}},"required":["id","name","title","description","titleOverride","descriptionOverride","fields","values"]}}},"required":["key","label","entries"]},"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"]},"CreateJobBody":{"type":"object","properties":{"companyId":{"type":"string","minLength":1,"description":"The ID of an existing company. **Required unless you supply `company`** — exactly one of the two must be present, and supplying both is an error."},"description":{"type":"string","minLength":1,"maxLength":25000,"description":"Long-form description of the role, as HTML. Up to 25,000 characters. The HTML is sanitized on write: tags and attributes outside the supported formatting set (paragraphs, headings, lists, links, inline emphasis) are removed. Plain text without HTML tags is converted to paragraphs."},"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. When `customEmploymentType` is also sent, this must be the Google equivalent of that custom type (or be omitted: the server sets it). Sending a built-in type without `customEmploymentType` clears any custom type on the job."},"customEmploymentType":{"type":"string","nullable":true,"minLength":1,"maxLength":100,"description":"Key of one of the board's custom employment types (`GET /v1/settings/job-form` → `employmentType.customTypes`). The job is saved with the Google equivalent of that type as its built-in `employmentType`, which is what Google for Jobs and feeds see. An unknown key, a type the board no longer offers (`offered: false`), or an `employmentType` that differs from its Google equivalent returns `400 jobs_constraint_violation`. Pass `null` to clear the custom type and keep the built-in; omitted means unchanged."},"remoteOption":{"type":"string","enum":["on_site","hybrid","remote"],"description":"**Required.** Whether the role is on-site, hybrid, or fully remote: one of `on_site`, `hybrid`, `remote`. Omitting it or sending `null` returns `400`. It is not valid on its own either: `on_site` and `hybrid` require at least one `officeLocations` entry, and `remote` requires `remotePermits` (use `[{\"type\":\"worldwide\",\"value\":\"worldwide\"}]` for anywhere; `remoteTimezones` then auto-derives on POST)."},"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","nullable":true,"minimum":0,"description":"Minimum salary, in `salaryCurrency` units. `null` means not set. When `salaryMin` or `salaryMax` is set, `salaryCurrency` and `salaryTimeframe` are both required; otherwise `400`."},"salaryMax":{"type":"number","nullable":true,"minimum":0,"description":"Maximum salary, in `salaryCurrency` units. `null` means not set. When `salaryMin` or `salaryMax` is set, `salaryCurrency` and `salaryTimeframe` are both required; otherwise `400`."},"salaryCurrency":{"type":"string","nullable":true,"description":"Three-letter ISO 4217 currency code for `salaryMin` and `salaryMax`. `null` means not set. Required when `salaryMin` or `salaryMax` is set; optional otherwise."},"salaryTimeframe":{"type":"string","nullable":true,"enum":["per_year","per_month","per_week","per_day","per_hour"],"description":"Period the `salaryMin` and `salaryMax` figures are quoted against. `null` means not set. Required when `salaryMin` or `salaryMax` is set; optional otherwise."},"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}],"description":"Job expiry as a Unix epoch in milliseconds. On create, omitted or `null` defaults to 30 days from creation. On PATCH, `null` clears the explicit expiry; an ordinary published job then receives the board's `defaultJobDurationDays` from its publication time (30 days when unset). Draft and sponsored jobs may have no 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. Prefer `{query: \"City, Country\"}` for free-form input; `{city, country, region?, locality?}` is also accepted when you already have structured fields. Each entry is resolved server-side; a country mismatch returns `400 jobs_unresolvable_location`."},"externalId":{"type":"string","nullable":true,"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. Always set it on create (the source job URL or ATS requisition ID) so reposts of the same job are detected reliably, even when several jobs share one `applicationUrl`. Scoped per-account: two different accounts may reuse the same `externalId` without collision. Up to 255 characters. `null` means not set."},"customFieldValues":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"boolean"},{"type":"number"},{"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."},"collectionValues":{"type":"object","additionalProperties":{"anyOf":[{"type":"array","items":{"type":"string"},"maxItems":100},{"nullable":true}]},"description":"Collection-reference selections keyed by the configured job collection field key. Values are arrays of record IDs, including for single-select fields. On PATCH omitted keys are preserved; send null or an empty array to clear a field."},"collectionOverrides":{"type":"array","items":{"$ref":"#/components/schemas/JobCollectionOverride"},"maxItems":500,"description":"Per-job wording for selected collection entries, only on fields whose definition has `allowOverrides`. At most one item per selected entry; an item for an entry that is not selected on the job is rejected with `400 jobs_constraint_violation`. The list replaces the job's stored overrides: on PATCH omit it to keep them and send `[]` to clear them all. Deselecting an entry through `collectionValues` drops its override."},"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`, `archived`, and `pending_approval` are not. Use the dedicated transitions (`POST /v1/jobs/:id/publish`, `/pause`, `/expire`) for status changes after create."},"allowSharedApplicationUrl":{"type":"boolean","description":"Set to `true` to create this job even though another job on your account already uses the same `applicationUrl` (for example, several roles that share one ATS page or one application inbox). Only skips the application-URL duplicate check; a matching `externalId` or an identical job (same company, title, location and description) still returns 409 `jobs_already_exists`. Defaults to `false`."}},"required":["description","remoteOption","applicationUrl","title"],"additionalProperties":false},"JobOfficeLocationInput":{"anyOf":[{"type":"object","properties":{"query":{"type":"string","minLength":1,"maxLength":500,"description":"Free-form location string (e.g. `\"Berlin, Germany\"`, `\"Utrecht, Netherlands\"`, `\"Mountain View, California, USA\"`). Resolved server-side; rejected when no high-confidence match is found."}},"required":["query"],"additionalProperties":false},{"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}]},"JobCollectionOverride":{"type":"object","properties":{"fieldKey":{"type":"string","minLength":1,"description":"The collection field key used in `collectionValues`."},"recordId":{"type":"string","minLength":1,"description":"A record ID selected for that field on this job."},"title":{"type":"string","maxLength":160,"description":"The entry's title on this job, up to 160 characters. Omit or send a blank string to use the entry name."},"description":{"type":"string","maxLength":2000,"description":"The entry's description on this job, up to 2000 characters of plain text. When the default description field is rich text, the entry's `description` returns it escaped as HTML. Omit or send a blank string to use the default description."}},"required":["fieldKey","recordId"]},"InlineCompanyInput":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120,"description":"The company's display name."},"website":{"type":"string","nullable":true,"maxLength":200,"description":"Public company website URL. Used to resolve to an existing company by domain before falling back to creation. `null` or `\"\"` means not set."},"summary":{"type":"string","nullable":true,"maxLength":280,"description":"One-line summary of the company. Up to 280 characters. `null` or `\"\"` means not set."},"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. **Required unless you supply `companyId`** — exactly one of the two must be present, and supplying both is an error."},"DuplicateJobBody":{"type":"object","properties":{},"additionalProperties":false},"PublishJobBody":{"type":"object","properties":{"expiresAt":{"type":"string","nullable":true,"format":"date-time","description":"New explicit expiry as an ISO 8601 datetime. Pass `null` to clear the explicit expiry, or omit the field to preserve an existing expiry. An ordinary published job without an explicit expiry receives the board's `defaultJobDurationDays` from its publication time (30 days when unset). Sponsored jobs may have no expiry."}},"additionalProperties":false},"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","pending_approval"]},"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 built-in employment types. Up to 10 values. A built-in value matches jobs of that type that have no custom employment type: a job with a custom type matches only through `customEmploymentType`. Combined with `customEmploymentType` as a union."},"customEmploymentType":{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":10,"description":"Only return jobs with any of the given custom employment type keys (the board's `customTypes`). Up to 10 values. Combined with `employmentType` as a union: a job matches when it has one of these custom types OR one of the given built-in types and no custom type."},"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."},"customFields":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"maxLength":64},"values":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]},"minItems":1,"maxItems":10}},"required":["key","values"],"additionalProperties":false},"maxItems":10,"description":"Match every custom-field clause; values within one clause are alternatives."}},"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},"MarketingPermission":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["marketing_permission"]},"email":{"type":"string"},"display_name":{"type":"string","nullable":true},"role":{"type":"string"},"status":{"type":"string","enum":["granted","withdrawn"]},"source":{"type":"string"},"reason":{"type":"string","nullable":true,"enum":["person_request","operator_request","account_deleted"]},"granted_at":{"type":"string","nullable":true},"withdrawn_at":{"type":"string","nullable":true},"updated_at":{"type":"string"},"revision":{"type":"integer"}},"required":["id","object","email","display_name","role","status","source","reason","granted_at","withdrawn_at","updated_at","revision"]},"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 plus the lower levels they include (`publish` includes `manage`, `manage` includes `read`); 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"]},"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"]},"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, as HTML. Up to 25,000 characters. The HTML is sanitized on write: tags and attributes outside the supported formatting set (paragraphs, headings, lists, links, inline emphasis) are removed. Plain text without HTML tags is converted to paragraphs."},"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. When `customEmploymentType` is also sent, this must be the Google equivalent of that custom type (or be omitted: the server sets it). Sending a built-in type without `customEmploymentType` clears any custom type on the job."},"customEmploymentType":{"type":"string","nullable":true,"minLength":1,"maxLength":100,"description":"Key of one of the board's custom employment types (`GET /v1/settings/job-form` → `employmentType.customTypes`). The job is saved with the Google equivalent of that type as its built-in `employmentType`, which is what Google for Jobs and feeds see. An unknown key, a type the board no longer offers (`offered: false`), or an `employmentType` that differs from its Google equivalent returns `400 jobs_constraint_violation`. Pass `null` to clear the custom type and keep the built-in; omitted means unchanged."},"remoteOption":{"type":"string","enum":["on_site","hybrid","remote"],"description":"Whether the role is on-site, hybrid, or fully remote. Omitted means unchanged; `null` returns `400` because a job's workplace type can be changed but not cleared. **Never valid on its own:** `on_site` and `hybrid` require at least one `officeLocations` entry, and `remote` requires `remotePermits` (use `[{\"type\":\"worldwide\",\"value\":\"worldwide\"}]` for anywhere; `remoteTimezones` then auto-derives on POST). Sending it alone returns `400`."},"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","nullable":true,"enum":["entry_level","associate","mid_level","senior","lead","principal","director","executive"],"description":"Seniority level of the role. Pass `null` to clear the stored value; omitted means unchanged."},"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","nullable":true,"minimum":0,"description":"Minimum salary, in `salaryCurrency` units. Pass `null` to clear the stored value; omitted means unchanged. When a request sends any salary field, the resulting salary (sent values over stored ones) must have `salaryCurrency` and `salaryTimeframe` whenever `salaryMin` or `salaryMax` is set; otherwise `400`. Requests that send no salary field are not checked."},"salaryMax":{"type":"number","nullable":true,"minimum":0,"description":"Maximum salary, in `salaryCurrency` units. Pass `null` to clear the stored value; omitted means unchanged. When a request sends any salary field, the resulting salary (sent values over stored ones) must have `salaryCurrency` and `salaryTimeframe` whenever `salaryMin` or `salaryMax` is set; otherwise `400`. Requests that send no salary field are not checked."},"salaryCurrency":{"type":"string","nullable":true,"description":"Three-letter ISO 4217 currency code for `salaryMin` and `salaryMax`. Pass `null` to clear the stored value; omitted means unchanged. When a request sends any salary field, the resulting salary (sent values over stored ones) must have `salaryCurrency` and `salaryTimeframe` whenever `salaryMin` or `salaryMax` is set; otherwise `400`. Requests that send no salary field are not checked."},"salaryTimeframe":{"type":"string","nullable":true,"enum":["per_year","per_month","per_week","per_day","per_hour"],"description":"Period the `salaryMin` and `salaryMax` figures are quoted against. Pass `null` to clear the stored value; omitted means unchanged. When a request sends any salary field, the resulting salary (sent values over stored ones) must have `salaryCurrency` and `salaryTimeframe` whenever `salaryMin` or `salaryMax` is set; otherwise `400`. Requests that send no salary field are not checked."},"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}],"description":"Job expiry as a Unix epoch in milliseconds. On create, omitted or `null` defaults to 30 days from creation. On PATCH, `null` clears the explicit expiry; an ordinary published job then receives the board's `defaultJobDurationDays` from its publication time (30 days when unset). Draft and sponsored jobs may have no 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. Prefer `{query: \"City, Country\"}` for free-form input; `{city, country, region?, locality?}` is also accepted when you already have structured fields. Each entry is resolved server-side; a country mismatch returns `400 jobs_unresolvable_location`."},"externalId":{"type":"string","nullable":true,"minLength":1,"maxLength":255,"description":"An external identifier for the job from your own system, such as an ATS requisition ID. Pass `null` to clear the stored value; omitted means unchanged."},"customFieldValues":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"boolean"},{"type":"number"},{"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."},"collectionValues":{"type":"object","additionalProperties":{"anyOf":[{"type":"array","items":{"type":"string"},"maxItems":100},{"nullable":true}]},"description":"Collection-reference selections keyed by the configured job collection field key. Values are arrays of record IDs, including for single-select fields. On PATCH omitted keys are preserved; send null or an empty array to clear a field."},"collectionOverrides":{"type":"array","items":{"$ref":"#/components/schemas/JobCollectionOverride"},"maxItems":500,"description":"Per-job wording for selected collection entries, only on fields whose definition has `allowOverrides`. At most one item per selected entry; an item for an entry that is not selected on the job is rejected with `400 jobs_constraint_violation`. The list replaces the job's stored overrides: on PATCH omit it to keep them and send `[]` to clear them all. Deselecting an entry through `collectionValues` drops its override."},"title":{"type":"string","minLength":1,"maxLength":200,"description":"The job title."}},"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."},"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."},"builderCredits":{"$ref":"#/components/schemas/BuilderCreditUsage"}},"required":["object","capacities","builderCredits"]},"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"]},"BuilderCreditUsage":{"type":"object","properties":{"daily":{"type":"object","properties":{"periodKey":{"type":"string"},"usedTenths":{"type":"integer","minimum":0},"limitTenths":{"type":"integer","nullable":true,"minimum":0},"remainingTenths":{"type":"integer","nullable":true,"minimum":0}},"required":["periodKey","usedTenths","limitTenths","remainingTenths"]},"monthly":{"type":"object","properties":{"periodKey":{"type":"string"},"usedTenths":{"type":"integer","minimum":0},"limitTenths":{"type":"integer","nullable":true,"minimum":0},"remainingTenths":{"type":"integer","nullable":true,"minimum":0},"resetsAtMs":{"type":"integer","minimum":0}},"required":["periodKey","usedTenths","limitTenths","remainingTenths","resetsAtMs"]},"grantedTenths":{"type":"integer","minimum":0}},"required":["daily","monthly","grantedTenths"],"description":"Builder credit usage in tenths of a credit for the current day and billing period, plus spendable granted credits."},"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"]},"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"]},"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"]},"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"]},"BlockCompanyResult":{"type":"object","properties":{"id":{"type":"string","description":"The blocked company id."},"blocked":{"type":"boolean","enum":[true]},"jobs_archived_scheduled":{"type":"boolean","description":"Whether a published-job archive pass was scheduled."},"was_already_blocked":{"type":"boolean","description":"True when the company was already on the blocklist."},"removed":{"type":"boolean","description":"True when the company is removed from the board as well as blocked."},"removal_scheduled":{"type":"boolean","description":"Whether this call scheduled the removal of the profile and its jobs."}},"required":["id","blocked","jobs_archived_scheduled","was_already_blocked","removed","removal_scheduled"]},"BlockCompanyBody":{"type":"object","properties":{"reason":{"type":"string","maxLength":500,"description":"Optional free-text reason recorded on the blocklist audit."},"remove":{"type":"boolean","description":"When true, also removes the company profile and its jobs from the board while keeping it on the blocklist (ADR-0124); default false keeps the profile and archives published jobs."}},"additionalProperties":false},"UnblockCompanyResult":{"type":"object","properties":{"id":{"type":"string","description":"The unblocked company id."},"blocked":{"type":"boolean","enum":[false]},"was_blocked":{"type":"boolean","description":"True when the company was on the blocklist before this call."},"was_removed":{"type":"boolean","description":"True when the company had also been removed from the board before this call."}},"required":["id","blocked","was_blocked","was_removed"]},"CompanyPlanAssignment":{"type":"object","properties":{"id":{"type":"string","description":"The plan assignment ID."},"object":{"type":"string","enum":["company_plan_assignment"]},"companyId":{"type":"string"},"planId":{"type":"string","nullable":true,"description":"The assigned plan. Null for a custom level granted in the dashboard without a plan."},"planName":{"type":"string","nullable":true},"source":{"type":"string","enum":["manual","purchase","invoice","synced"],"description":"`manual`: assigned by an operator. `purchase`: bought at checkout. `invoice`: granted when a plan invoice was paid. `synced`: set by a membership sync."},"status":{"type":"string","enum":["active","expired","revoked"],"description":"Only `active` assignments give the company its plan benefits."},"expiresAt":{"type":"string","nullable":true,"description":"ISO-8601 time the assignment ends, or null for no end."},"createdAt":{"type":"string","description":"ISO-8601 creation time."},"updatedAt":{"type":"string","description":"ISO-8601 time of the last change."}},"required":["id","object","companyId","planId","planName","source","status","expiresAt","createdAt","updatedAt"]},"CreateCompanyPlanAssignmentBody":{"type":"object","properties":{"planId":{"type":"string","minLength":1,"description":"An active (not archived) plan with `purpose: membership` on this board."},"expiresAt":{"type":"string","format":"date-time","description":"ISO-8601 time the assignment ends; must be in the future. Omit for no end."}},"required":["planId"],"additionalProperties":false},"CompanyPlanInvoice":{"type":"object","properties":{"id":{"type":"string","description":"The plan invoice ID."},"object":{"type":"string","enum":["company_plan_invoice"]},"companyId":{"type":"string"},"planId":{"type":"string"},"planName":{"type":"string","nullable":true},"status":{"type":"string","enum":["issued","paid","canceled","uncollectible"],"description":"`issued`: awaiting payment. `paid`: paid, and the plan was assigned to the company. `canceled`: canceled before payment. `uncollectible`: marked uncollectible in Stripe."},"amountCents":{"type":"integer","description":"Amount per invoice, in currency minor units."},"currency":{"type":"string","description":"Lowercase ISO 4217 currency code."},"billingInterval":{"type":"string","nullable":true,"enum":["month","year"],"description":"Null for a one-off invoice; otherwise how often it recurs."},"billingIntervalCount":{"type":"integer","nullable":true,"description":"Number of intervals between invoices (3 months = quarterly)."},"contactEmail":{"type":"string","description":"The billing email the invoice is for."},"hostedInvoiceUrl":{"type":"string","nullable":true,"description":"The payment page for the employer. Cavuno does not send the invoice itself; share this link with them."},"dueAt":{"type":"string","nullable":true,"description":"ISO-8601 due date (30 days after issue)."},"assignmentId":{"type":"string","nullable":true,"description":"The plan assignment created when the invoice was paid; null until then."},"createdAt":{"type":"string","description":"ISO-8601 creation time."},"updatedAt":{"type":"string","description":"ISO-8601 time of the last change."}},"required":["id","object","companyId","planId","planName","status","amountCents","currency","billingInterval","billingIntervalCount","contactEmail","hostedInvoiceUrl","dueAt","assignmentId","createdAt","updatedAt"]},"CreateCompanyPlanInvoiceBody":{"type":"object","properties":{"planId":{"type":"string","minLength":1,"description":"An active (not archived) plan with `purpose: membership` on this board."},"contactEmail":{"type":"string","format":"email","description":"Billing email of the employer who will pay."},"amountCents":{"type":"integer","minimum":1,"maximum":99999999,"description":"Amount per invoice in currency minor units. Required when the plan has no price; rejected when it has one."},"currency":{"type":"string","pattern":"^[A-Za-z]{3}$","description":"ISO 4217 currency code. Send it together with `amountCents`."},"billingInterval":{"type":"string","enum":["month","year"],"description":"Make the invoice recur. Omit for a one-off invoice. Rejected when the plan is a subscription with its own interval, which then sets the terms."},"billingIntervalCount":{"type":"integer","minimum":1,"maximum":12,"description":"Intervals between invoices (default 1; `month` with 3 is quarterly). Needs `billingInterval`."}},"required":["planId","contactEmail"],"additionalProperties":false},"AgentFeedbackAccepted":{"type":"object","properties":{"id":{"type":"string","description":"The report id, e.g. `fb_…`."},"status":{"type":"string","enum":["accepted"]},"received_at":{"type":"string","description":"When Cavuno first received this report (ISO 8601). A retry returns the original time."}},"required":["id","status","received_at"]},"AgentFeedbackError":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"`invalid_json`, `invalid_feedback`, `payload_too_large`, `unsupported_media_type`, `rate_limited`, `rate_limit_unavailable` or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation."},"details":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]},"description":"Every problem with the report, for `invalid_feedback`."}},"required":["code","message"]}},"required":["error"]},"AgentFeedbackReport":{"type":"object","properties":{"type":{"type":"string","enum":["missing_capability","bug","unclear_documentation","unexpected_response","unhelpful_error","performance","other"],"description":"The kind of problem."},"goal":{"type":"string","maxLength":1000,"description":"What you or your user were trying to accomplish, in plain language."},"message":{"type":"string","maxLength":4000,"description":"What prevented or complicated the task."},"endpoint":{"type":"string","maxLength":512,"description":"API path, CLI command or MCP tool involved, e.g. `/jobs`."},"method":{"type":"string","enum":["GET","POST","PUT","PATCH","DELETE","HEAD","OPTIONS"],"description":"HTTP method, when `endpoint` is a path."},"outcome":{"type":"string","enum":["blocked","degraded","completed"],"description":"`blocked`: the task failed. `degraded`: it finished worse or slower. `completed`: a suggestion only."},"workaround":{"type":"boolean","description":"Whether you found a workaround."},"workaround_description":{"type":"string","maxLength":2000,"description":"The workaround, if any."},"expected":{"type":"string","maxLength":2000,"description":"What you expected to find or happen."},"suggestion":{"type":"string","maxLength":2000,"description":"A concrete change that would have let you succeed."},"request_id":{"type":"string","maxLength":256,"description":"The `X-Request-Id` of the failing call, if you have it."},"session_id":{"type":"string","maxLength":256,"description":"Reuse one value for every report in a task; a retry with the same content returns the original report."},"agent":{"type":"object","properties":{"name":{"type":"string","maxLength":256},"version":{"type":"string","maxLength":256},"model":{"type":"string","maxLength":256},"framework":{"type":"string","maxLength":256}},"additionalProperties":false,"description":"Who is reporting: name (agent or product) and model."},"evidence":{"type":"object","properties":{"status_code":{"type":"integer"},"request":{"type":"object","additionalProperties":{"nullable":true}},"response_excerpt":{"type":"string","maxLength":4000}},"additionalProperties":false,"description":"Sanitized details of the failing call, with no credentials or personal data."},"metadata":{"type":"object","additionalProperties":{"nullable":true},"description":"Any other context, as a JSON object."},"spec_version":{"type":"string","enum":["0.1"],"description":"Protocol version. Only `0.1` is accepted."}},"required":["type","goal","message"],"additionalProperties":false},"WebhookEndpoint":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["webhook_endpoint"]},"url":{"type":"string"},"event_types":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["enabled","paused","failing"]},"failure_streak":{"type":"integer","minimum":0},"last_failure_at":{"type":"string","nullable":true},"last_success_at":{"type":"string","nullable":true},"health_changed_at":{"type":"string","nullable":true},"health_reason":{"type":"string","nullable":true,"enum":["consecutive_failures","retry_exhausted","http_410","operator_pause","operator_resume","synthetic_recovery"]},"secret_overlap_expires_at":{"type":"string","nullable":true},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","object","url","event_types","status","failure_streak","last_failure_at","last_success_at","health_changed_at","health_reason","secret_overlap_expires_at","created_at","updated_at"]},"WebhookEndpointCreated":{"allOf":[{"$ref":"#/components/schemas/WebhookEndpoint"},{"type":"object","properties":{"secret":{"type":"string","description":"Signing secret returned exactly once on create or rotate. Store it immediately."}},"required":["secret"]}]},"CreateWebhookEndpointBody":{"type":"object","properties":{"url":{"type":"string","maxLength":2048,"format":"uri","description":"Public HTTPS URL that will receive webhook deliveries."},"event_types":{"type":"array","items":{"type":"string","enum":["job.created","job.updated","job.deleted","company.created","company.updated","company.deleted","candidate.created","candidate.updated","candidate.deleted","candidate.profile.updated","marketing_permission.granted","marketing_permission.withdrawn"]},"minItems":1,"description":"V1 event types this endpoint subscribes to (unique)."}},"required":["url","event_types"],"additionalProperties":false},"UpdateWebhookEndpointBody":{"type":"object","properties":{"url":{"type":"string","maxLength":2048,"format":"uri"},"event_types":{"type":"array","items":{"type":"string","enum":["job.created","job.updated","job.deleted","company.created","company.updated","company.deleted","candidate.created","candidate.updated","candidate.deleted","candidate.profile.updated","marketing_permission.granted","marketing_permission.withdrawn"]},"minItems":1},"status":{"type":"string","enum":["enabled","paused"]}},"additionalProperties":false},"WebhookTestDelivery":{"type":"object","properties":{"object":{"type":"string","enum":["webhook_test_delivery"]},"delivered":{"type":"boolean"},"status":{"type":"number","nullable":true},"status_class":{"type":"string"},"latency_ms":{"type":"number"},"diagnostic":{"type":"string"}},"required":["object","delivered","status","status_class","latency_ms","diagnostic"]},"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},"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"]},"UpdateInvitationBody":{"type":"object","properties":{"role":{"type":"string","enum":["admin","member"],"description":"The new role for the pending invitation."}},"required":["role"]},"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":{"$ref":"#/components/schemas/SubscriberAlert"},"description":"The subscriber's alerts."}},"required":["lastSentAt","alerts"]}]},"SubscriberAlert":{"type":"object","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","enum":["weekly"],"description":"Weekly delivery cadence."},"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"]},"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"]},"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"]},"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}]},"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},"PageContent":{"type":"object","properties":{"object":{"type":"string","enum":["page_content"]},"category":{"type":"string","nullable":true,"description":"The category slug the page was addressed by."},"place":{"type":"string","nullable":true,"description":"The place slug the page was addressed by."},"intro":{"type":"string","description":"The intro markdown."},"source":{"type":"string","enum":["human","llm"]},"updatedAt":{"type":"string"}},"required":["object","category","place","intro","source","updatedAt"]},"PutPageContentBody":{"type":"object","properties":{"intro":{"type":"string","minLength":1,"maxLength":4000,"description":"Markdown shown above the job list on page 1 of the page. Served as sanitized HTML."},"source":{"type":"string","enum":["human","llm"],"default":"human","description":"`llm` marks an AI draft a person approved. Defaults to `human`."}},"required":["intro"],"additionalProperties":false},"PatchReportingIntegrationBody":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Whether collection is enabled for this integration."},"searchConsoleCoverageMode":{"type":"string","enum":["board_hosts","whole_property"],"description":"Search Console only. board_hosts restricts reads to stored Board hostnames; whole_property explicitly authorizes the entire selected Google property."}},"additionalProperties":false},"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"]},"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"]},"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"]},"BillingConnectOnboardingLink":{"type":"object","properties":{"object":{"type":"string","enum":["billing_connect_onboarding_link"]},"url":{"type":"string","format":"uri","description":"Single-use hosted Stripe onboarding URL. Hand it to a human straight away; it expires within minutes."},"expiresAt":{"type":"string","format":"date-time","description":"ISO 8601 time after which the URL no longer works."}},"required":["object","url","expiresAt"]},"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":["day","week","month","year"],"description":"Subscription billing interval. Required for kind=subscription. Pair with billingIntervalCount for non-1 counts (quarterly = month × 3)."},"billingIntervalCount":{"type":"integer","nullable":true,"minimum":1,"description":"Stripe recurring.interval_count. Null/omitted means 1. Quarterly is month × 3."},"purpose":{"type":"string","enum":["job_posting","talent_access","membership","job_seeker","employer_service","job_seeker_service"],"description":"What the plan entitles: job-posting, talent-access, membership (employer membership), job-seeker (candidate paywall), or contact-led employer_service / job_seeker_service catalogue rows."},"isPublic":{"type":"boolean"},"isRecommended":{"type":"boolean"},"isArchived":{"type":"boolean"},"displayOrder":{"type":"number","nullable":true},"pricingMode":{"type":"string","enum":["priced","contact"],"description":"How the plan is sold. Plans created before this field existed report `priced`."},"priceText":{"type":"string","nullable":true,"description":"Operator-authored display price text for a contact plan, e.g. \"From $2,000\". Null when unset."},"ctaText":{"type":"string","nullable":true,"description":"Operator-authored CTA label for a contact plan."},"ctaDestination":{"type":"string","nullable":true,"description":"The CTA target: an https, mailto:, or tel: URL. Null when unset, in which case no CTA is rendered."},"price":{"$ref":"#/components/schemas/PlanPrice"},"features":{"type":"array","items":{"$ref":"#/components/schemas/PlanFeature"}}},"required":["id","object","name","description","kind","billingInterval","billingIntervalCount","purpose","isPublic","isRecommended","isArchived","displayOrder","pricingMode","priceText","ctaText","ctaDestination","price","features"]},"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."},"PlanFeature":{"type":"object","properties":{"key":{"type":"string","enum":["jobs.max_active","jobs.included_posts","jobs.duration_days","jobs.featured_slots","jobs.included_featured","jobs.feature_selection_mode","jobs.posting_discount_percent","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"]},"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":["day","week","month","year"],"description":"Subscription billing interval. Required for kind=subscription. Pair with billingIntervalCount for non-1 counts (quarterly = month × 3)."},"billingIntervalCount":{"type":"integer","minimum":1},"purpose":{"type":"string","enum":["job_posting","talent_access","membership","job_seeker","employer_service","job_seeker_service"],"description":"What the plan entitles: job-posting, talent-access, membership (employer membership), job-seeker (candidate paywall), or contact-led employer_service / job_seeker_service catalogue rows."},"isPublic":{"type":"boolean","description":"Whether the plan is publicly listed. Defaults to false."},"isRecommended":{"type":"boolean"},"displayOrder":{"type":"integer"},"pricingMode":{"type":"string","enum":["priced","contact"],"description":"How the plan is sold. `priced` takes a price and syncs it to Stripe; `contact` renders a contact CTA and creates no Stripe objects — setting a price on a contact plan is rejected. Omitted on create means `priced`."},"priceText":{"type":"string","description":"Display price text for a contact plan, e.g. \"Contact us\"."},"ctaText":{"type":"string","description":"CTA label for a contact plan, e.g. \"Talk to sales\"."},"ctaDestination":{"type":"string","description":"CTA target for a contact plan. Must be an https, mailto:, or tel: URL."}},"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"},"pricingMode":{"type":"string","enum":["priced","contact"],"description":"How the plan is sold. `priced` takes a price and syncs it to Stripe; `contact` renders a contact CTA and creates no Stripe objects — setting a price on a contact plan is rejected. Omitted on create means `priced`."},"priceText":{"type":"string","description":"Display price text for a contact plan. Send an empty string to clear it."},"ctaText":{"type":"string","description":"CTA label for a contact plan. Empty string clears it."},"ctaDestination":{"type":"string","description":"CTA target for a contact plan. Must be an https, mailto:, or tel: URL. Empty string clears it."}},"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},"PlanFeatureValue":{"type":"object","properties":{"key":{"type":"string","enum":["jobs.max_active","jobs.included_posts","jobs.duration_days","jobs.featured_slots","jobs.included_featured","jobs.feature_selection_mode","jobs.posting_discount_percent","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.included_posts","jobs.duration_days","jobs.featured_slots","jobs.included_featured","jobs.feature_selection_mode","jobs.posting_discount_percent","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}}},"paths":{"/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"}},"/settings/profile-fields/{entity}":{"get":{"operationId":"listProfileFieldDefinitions","summary":"List profile custom-field definitions","description":"Lists candidate or company profile field definitions in display order. Includes private definitions. Requires `settings.read`.","parameters":[{"schema":{"type":"string","enum":["candidate","company"]},"required":true,"name":"entity","in":"path"}],"responses":{"200":{"description":"Definition list.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProfileCustomFieldDefinition"}}}}},"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"]},"put":{"operationId":"replaceProfileFieldDefinitions","summary":"Replace profile custom-field definitions","description":"Replaces candidate or company definitions wholesale. Array order is display order. Existing field types are immutable. Requires `settings.manage`.","parameters":[{"schema":{"type":"string","enum":["candidate","company"]},"required":true,"name":"entity","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplaceProfileFieldDefinitionsBody"}}}},"responses":{"200":{"description":"Updated definition list.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProfileCustomFieldDefinition"}}}}},"422":{"description":"An existing field type was changed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Settings"]}},"/candidates/{id}/custom-fields":{"get":{"operationId":"getCandidateCustomFieldValues","summary":"Get candidate custom-field values","description":"Returns all candidate profile values, including private fields. Requires `candidates.read`.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Profile custom-field definitions and values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileFieldValuesResponse"}}}},"404":{"description":"Profile not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Candidates"]},"patch":{"operationId":"updateCandidateCustomFieldValues","summary":"Update candidate custom-field values","description":"Additive update of candidate profile values. Omitted keys are preserved; null, blank strings, and empty arrays clear a value; false and 0 are preserved. Requires `candidates.manage`.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileFieldValuesBody"}}}},"responses":{"200":{"description":"Profile custom-field definitions and values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileFieldValuesResponse"}}}},"404":{"description":"Profile not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Candidates"]}},"/companies/{id}/custom-fields":{"get":{"operationId":"getCompanyCustomFieldValues","summary":"Get company custom-field values","description":"Returns all company profile values, including private fields. Requires `companies.read`.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Profile custom-field definitions and values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileFieldValuesResponse"}}}},"404":{"description":"Profile not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Companies"]},"patch":{"operationId":"updateCompanyCustomFieldValues","summary":"Update company custom-field values","description":"Additive update of company profile values. Omitted keys are preserved; null, blank strings, and empty arrays clear a value; false and 0 are preserved. Requires `companies.manage`.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileFieldValuesBody"}}}},"responses":{"200":{"description":"Profile custom-field definitions and values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileFieldValuesResponse"}}}},"404":{"description":"Profile not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Companies"]}},"/settings/profile-object-references/{entity}":{"get":{"operationId":"listProfileObjectReferenceDefinitions","summary":"List profile object reference definitions","parameters":[{"schema":{"type":"string","enum":["candidate","company"]},"required":true,"name":"entity","in":"path"}],"responses":{"200":{"description":"Reference definitions.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProfileObjectReferenceDefinition"}}}}},"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"]},"put":{"operationId":"replaceProfileObjectReferenceDefinitions","summary":"Replace profile object reference definitions","parameters":[{"schema":{"type":"string","enum":["candidate","company"]},"required":true,"name":"entity","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"definitions":{"type":"array","items":{"$ref":"#/components/schemas/ProfileObjectReferenceDefinition"},"maxItems":50}},"required":["definitions"],"additionalProperties":false}}}},"responses":{"200":{"description":"Reference definitions.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProfileObjectReferenceDefinition"}}}}},"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"]}},"/candidates/{id}/object-references":{"get":{"operationId":"getCandidateObjectReferences","summary":"Get candidate object references","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Candidate references.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileObjectReferencesResult"}}}},"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"]},"put":{"operationId":"replaceCandidateObjectReferences","summary":"Replace candidate object references","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplaceProfileObjectReferenceSelectionsBody"}}}},"responses":{"200":{"description":"Candidate references.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileObjectReferencesResult"}}}},"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"]}},"/companies/{id}/object-references":{"get":{"operationId":"getCompanyObjectReferences","summary":"Get company object references","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Company references.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileObjectReferencesResult"}}}},"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"]},"put":{"operationId":"replaceCompanyObjectReferences","summary":"Replace company object references","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplaceProfileObjectReferenceSelectionsBody"}}}},"responses":{"200":{"description":"Company references.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileObjectReferencesResult"}}}},"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"]}},"/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}/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"}},"/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"}},"/candidates/{id}/profile":{"get":{"summary":"Get a candidate profile snapshot","description":"Returns the canonical candidate sync snapshot: identity, profile scalars, and collections. Excludes credentials, resume storage internals, applications, messages, saved jobs, and consent state. Requires `candidates.read`.","parameters":[{"schema":{"type":"string","minLength":1,"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/CandidateSyncSnapshot"}}}},"404":{"description":"Candidate not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Candidate has more related records than this endpoint supports.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Candidates"],"operationId":"getCandidateProfile"},"put":{"summary":"Replace a candidate profile","description":"Replaces the selected profile projection. The write body is a desired-state projection, not the GET response shape: scalars are top-level, and read-only fields are rejected. Absent keys are left unchanged; `null` on a scalar clears it; providing a collection array replaces that collection wholesale (empty array clears). Requires `candidates.manage`. The request is idempotent when an `Idempotency-Key` header is supplied.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The candidate id."},"required":true,"description":"The candidate id.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateProfileProjection"}}}},"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateSyncSnapshot"}}}},"400":{"description":"The request was malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Candidate not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Candidate has more related records than this endpoint supports.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Candidates"],"operationId":"updateCandidateProfile"}},"/candidates":{"post":{"summary":"Create a candidate","description":"Creates a passwordless candidate. Magic link is the default activation. An optional initial profile is seeded once. Requires `candidates.manage`. The request is idempotent when an `Idempotency-Key` header is supplied.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCandidateBody"}}}},"responses":{"201":{"description":"Candidate created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateDetail"}}}},"400":{"description":"The request was malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The email is already registered to another board user on this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Candidates"],"operationId":"createCandidate"},"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/{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"},"patch":{"summary":"Update a candidate","description":"Updates the candidate email and/or display name. Omitted fields are left unchanged. Requires `candidates.manage`. The request is idempotent when an `Idempotency-Key` header is supplied.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The candidate id."},"required":true,"description":"The candidate id.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCandidateBody"}}}},"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateDetail"}}}},"400":{"description":"The request was malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Candidate not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The email is already registered to another board user on this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Candidates"],"operationId":"updateCandidate"}},"/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"}},"/candidates/{id}/reactivate":{"post":{"summary":"Reactivate a candidate","description":"Restores sign-in, session access, and talent-surface visibility for a previously deactivated candidate. Profile and application history were preserved by deactivate. Idempotent: an already-active candidate returns 200 with the unchanged detail. Requires `candidates.manage`. The request is idempotent when an `Idempotency-Key` header is supplied.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The candidate id."},"required":true,"description":"The candidate id.","name":"id","in":"path"}],"responses":{"200":{"description":"Candidate reactivated. `deactivatedAt` is `null`. Sign-in, session access, and talent-surface visibility are restored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateDetail"}}}},"404":{"description":"Candidate not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Candidates"],"operationId":"reactivateCandidate"}},"/candidates/reconcile":{"post":{"summary":"Reconcile a candidate from a membership source","description":"Body-keyed membership sync. `sourceKey` + `externalMemberId` identify the member; they stay in the body because request paths land in logs. `sourceRevision` orders writes: equal is a no-op, lower is rejected. Creates, links, or updates the Candidate and optionally applies a profile projection. Pair this push with the `candidate.profile.updated` webhook and `GET /candidates/{id}/profile` pull. Requires `candidates.manage`. The request is idempotent when an `Idempotency-Key` header is supplied; equal source revisions are also idempotent without the header.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReconcileCandidateBody"}}}},"responses":{"200":{"description":"Candidate reconciled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateReconcileResult"}}}},"400":{"description":"The request was malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The email is taken, a newer source revision has already been applied, this candidate is already linked to a different member id for this source, or `sandbox_persona_protected` when a reconcile changes a persona's email or deactivates a persona on a sandbox board.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Candidates"],"operationId":"reconcileCandidate"}},"/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/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/{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. Pass `block=true` to delete and block: the company is removed from the board and stays on the blocklist, so automated sourcing cannot recreate it. Deleting a company that is on the blocklist never takes it off the blocklist: the company stays blocked and is removed from the board instead of being purged (ADR-0124). To purge a blocked company completely, unblock it first and then delete it.","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","enum":["true","false"],"description":"Pass `true` to delete and block: the company is removed from the board and kept on the blocklist, so backfill, imports and the API cannot add it back until it is unblocked. Defaults to `false`, a plain delete after which backfill may add the company again if it still matches the board’s sources. Ignored for a company whose website domain is shared with another company on the board, which is always a plain delete."},"required":false,"description":"Pass `true` to delete and block: the company is removed from the board and kept on the blocklist, so backfill, imports and the API cannot add it back until it is unblocked. Defaults to `false`, a plain delete after which backfill may add the company again if it still matches the board’s sources. Ignored for a company whose website domain is shared with another company on the board, which is always a plain delete.","name":"block","in":"query"}],"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}/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"}},"/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","pending_approval"],"description":"Only return jobs matching the given status. One of `draft`, `published`, `expired`, `archived`, or `pending_approval` (awaiting operator approval). `draft` does not include jobs awaiting approval."},"required":false,"description":"Only return jobs matching the given status. One of `draft`, `published`, `expired`, `archived`, or `pending_approval` (awaiting operator approval). `draft` does not include jobs awaiting approval.","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/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"}},"/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"}},"/media/upload-intents":{"post":{"operationId":"createMediaUploadIntent","summary":"Create a staged media upload intent","description":"Creates a short-lived direct-upload intent for media bytes that cannot travel through a JSON or code argument. POST the original file bytes to the returned uploadUrl, then complete the intent with the returned storageId.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaUploadIntentCreate"}}}},"responses":{"201":{"description":"Upload intent created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaUploadIntent"}}}},"400":{"description":"The upload metadata is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The caller lacks permission for this purpose.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The declared file size exceeds the purpose limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The declared MIME type is unsupported.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many uploads.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Media"]}},"/media/upload-intents/{intentId}/complete":{"post":{"operationId":"completeMediaUploadIntent","summary":"Complete a staged media upload","description":"Verifies the staged object against the intent using storage-owned byte length and MIME metadata, processes it through the normal media pipeline, and returns the resulting media object.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"example":"intent_01jxyz","name":"intentId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaUploadIntentComplete"}}}},"responses":{"201":{"description":"Upload completed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaUpload"}}}},"400":{"description":"The staged byte length or MIME type does not match the intent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The caller lacks permission for this purpose.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The intent or staged object was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The intent is already being completed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The staged file exceeds the purpose limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The staged MIME type is unsupported.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many uploads.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Media"]}},"/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/{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":{"deprecated":true,"summary":"List sales-led plans","description":"Deprecated. Use plans with `purpose: employer_service` and `pricingMode: contact`. 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":{"deprecated":true,"summary":"Create a sales-led plan","description":"Deprecated. Create an employer-service contact plan instead. This operation remains available for compatibility. 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/{id}":{"get":{"deprecated":true,"summary":"Retrieve a sales-led plan","description":"Deprecated. Use the corresponding employer-service contact plan. 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":{"deprecated":true,"summary":"Update a sales-led plan","description":"Deprecated. Update the corresponding employer-service contact plan. This compatibility operation replaces the editable fields of an active sales-led plan. 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/reorder":{"post":{"deprecated":true,"summary":"Reorder sales-led plans","description":"Deprecated. Reorder employer-service contact plans instead. This compatibility operation atomically sets `displayOrder` for the complete active sales-led 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}/publish":{"post":{"deprecated":true,"summary":"Publish a sales-led plan","description":"Deprecated. Publish the corresponding employer-service contact plan. This compatibility operation sets `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"}},"/sales-led-plans/{id}/hide":{"post":{"deprecated":true,"summary":"Hide a sales-led plan","description":"Deprecated. Hide the corresponding employer-service contact plan. This compatibility operation sets `isPublic: false` without archiving the sales-led row. 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}/archive":{"post":{"deprecated":true,"summary":"Archive a sales-led plan","description":"Deprecated. Archive the corresponding employer-service contact plan. This compatibility operation soft-deletes the sales-led row by setting `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"}},"/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/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"}},"/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. A field sent without `visibility` keeps its current visibility. The key of a deleted private field cannot be used for a new field (400), so its saved answers stay private. 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/form-layouts":{"get":{"summary":"Retrieve form layouts","description":"Retrieves the field order, visibility and required state of the job, company and talent forms. Requires `settings.read`. The public board context serves the same lists (public fields only) as `forms` for headless renderers.","responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormLayouts"}}}},"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":"getFormLayouts"},"put":{"summary":"Replace form layouts","description":"Replaces one or more of the job, company and talent form layouts. Each supplied list is the full ordered form; any field it leaves out is appended in the default order. The job form also updates the matching job form settings (salary and seniority visible and required, location visible). Rejected with 400 `validation_bad_request` for unknown or duplicate keys, a hidden or optional locked built-in, required on a hidden or non-requirable built-in, a hidden field whose definition is required, and any Google for Jobs rule; `error.details.issues` lists each problem as `{ form, code, key, message }`. Nothing is written unless every supplied list is valid. Requires `settings.manage`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplaceFormLayoutsBody"}}}},"responses":{"200":{"description":"The three form layouts after the write.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormLayouts"}}}},"400":{"description":"A layout was rejected. `error.details.issues` names each offending field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Settings"],"operationId":"replaceFormLayouts"}},"/sso-connections":{"get":{"summary":"List SSO connections","description":"Returns the board’s SSO connections, oldest first. A board has at most five.","responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"url":{"type":"string","example":"/v1/sso-connections"},"hasMore":{"type":"boolean"},"nextCursor":{"type":"string","nullable":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/SsoConnection"}}},"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":["Settings"],"operationId":"listSsoConnections"},"post":{"summary":"Create an SSO connection","description":"Creates a connection, switched off for both roles. Register its `callbackUrl` at the provider, run a test from the dashboard, then switch it on for candidates or employers with `PATCH`. Leave out `issuer` and `clientId` to create a draft and get its `callbackUrl` first; set them with `PATCH` before testing. The request is idempotent when an `Idempotency-Key` header is supplied.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSsoConnectionBody"}}}},"responses":{"201":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SsoConnection"}}}},"400":{"description":"A field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The board already has five SSO connections.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Settings"],"operationId":"createSsoConnection"}},"/sso-connections/{id}":{"get":{"summary":"Retrieve an SSO connection","description":"Retrieves one SSO connection.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The SSO connection ID returned by create or list endpoints."},"required":true,"description":"The SSO connection ID returned by create or list endpoints.","name":"id","in":"path"}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SsoConnection"}}}},"404":{"description":"SSO connection not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Settings"],"operationId":"getSsoConnection"},"patch":{"summary":"Update an SSO connection","description":"Updates the fields sent; `null` clears an optional field. On a connection that has passed a test, changes to provider settings wait in `pendingChanges` until a test passes on them and they are saved in the dashboard. Label, role switches, provisioning and trusted email apply at once.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The SSO connection ID returned by create or list endpoints."},"required":true,"description":"The SSO connection ID returned by create or list endpoints.","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSsoConnectionBody"}}}},"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SsoConnection"}}}},"400":{"description":"A field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"SSO connection not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A role switch was refused: the connection has not passed a test, or it is the only way that role can sign in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Settings"],"operationId":"updateSsoConnection"},"delete":{"summary":"Delete an SSO connection","description":"Deletes the connection and the identities linked through it. Board accounts stay. It cannot be undone. Refused while the connection is the only way a role can sign in.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The SSO connection ID returned by create or list endpoints."},"required":true,"description":"The SSO connection ID returned by create or list endpoints.","name":"id","in":"path"}],"responses":{"204":{"description":"Successful response."},"404":{"description":"SSO connection not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The connection is the only way a role can sign in (`sign_in_method_last`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Settings"],"operationId":"deleteSsoConnection"}},"/sso-connections/{id}/enable":{"post":{"deprecated":true,"summary":"Enable an SSO connection","description":"Deprecated: use PATCH with offeredToCandidates and offeredToEmployers. Keeps legacy role modes; disabling releases a legacy required-mode restriction. Modern last-method safeguards still apply.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The SSO connection ID returned by create or list endpoints."},"required":true,"description":"The SSO connection ID returned by create or list endpoints.","name":"id","in":"path"}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SsoConnection"}}}},"404":{"description":"SSO connection not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The connection is untested or this would remove the last working sign-in method.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Settings"],"operationId":"enableSsoConnection"}},"/sso-connections/{id}/disable":{"post":{"deprecated":true,"summary":"Disable an SSO connection","description":"Deprecated: use PATCH with offeredToCandidates and offeredToEmployers. Keeps legacy role modes; disabling releases a legacy required-mode restriction. Modern last-method safeguards still apply.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The SSO connection ID returned by create or list endpoints."},"required":true,"description":"The SSO connection ID returned by create or list endpoints.","name":"id","in":"path"}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SsoConnection"}}}},"404":{"description":"SSO connection not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The connection is untested or this would remove the last working sign-in method.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Settings"],"operationId":"disableSsoConnection"}},"/sso-connections/{id}/discard-pending":{"post":{"summary":"Discard pending SSO connection changes","description":"Drops `pendingChanges`. The live settings are untouched.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The SSO connection ID returned by create or list endpoints."},"required":true,"description":"The SSO connection ID returned by create or list endpoints.","name":"id","in":"path"}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SsoConnection"}}}},"404":{"description":"SSO connection not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Settings"],"operationId":"discardSsoConnectionPendingChanges"}},"/sso-connections/{id}/test-result":{"get":{"summary":"Retrieve the latest SSO connection test result","description":"The result of the latest connection test, kept for 30 minutes. Tests run in the operator’s browser from the dashboard.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The SSO connection ID returned by create or list endpoints."},"required":true,"description":"The SSO connection ID returned by create or list endpoints.","name":"id","in":"path"}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SsoConnectionTestResult"}}}},"404":{"description":"SSO connection or test result not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Settings"],"operationId":"getSsoConnectionTestResult"}},"/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"}},"/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/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","service"]},"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"}},"/webhook-deliveries":{"get":{"summary":"List webhook deliveries","description":"Returns Board-scoped delivery history, newest first. Optional filters: endpoint_id, status. Lease identity and raw event bodies are never included.","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,"description":"Filter to deliveries for a single endpoint."},"required":false,"description":"Filter to deliveries for a single endpoint.","name":"endpoint_id","in":"query"},{"schema":{"type":"string","enum":["pending","retrying","delivered","terminal","exhausted"],"description":"Filter by public delivery lifecycle status."},"required":false,"description":"Filter by public delivery 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/webhook-deliveries"},"hasMore":{"type":"boolean"},"nextCursor":{"type":"string","nullable":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}}},"required":["object","url","hasMore","nextCursor","data"]}}}},"402":{"description":"The board's plan does not include webhooks (`plan_upgrade_required`). Webhooks require a paid plan, Starter and above.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing webhooks.read or a family read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Webhooks"],"operationId":"listWebhookDeliveries"}},"/webhook-deliveries/{id}":{"get":{"summary":"Retrieve a webhook delivery","description":"Returns a delivery including its most recent attempt history (≤500 attempts, ascending by attempt_number). `attempt_count` is authoritative: when it exceeds `attempts.length`, older attempts were truncated. Never exposes lease fields or serialized event bodies.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The webhook delivery ID."},"required":true,"description":"The webhook delivery ID.","name":"id","in":"path"}],"responses":{"200":{"description":"Successful response. `attempts` holds the most recent ≤500 attempts in ascending order; `attempt_count > attempts.length` implies truncation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryDetail"}}}},"402":{"description":"The board's plan does not include webhooks (`plan_upgrade_required`). Webhooks require a paid plan, Starter and above.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing webhooks.read or a family read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Delivery not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Webhooks"],"operationId":"getWebhookDelivery"}},"/webhook-deliveries/{id}/replay":{"post":{"summary":"Replay a webhook delivery","description":"Resets a completed delivery (delivered, terminal, or exhausted) so the worker will attempt it again. Reuses the frozen event bytes and the occurrence-time endpoint configuration version; each attempt is signed with a fresh timestamp. Never creates a new domain event. Open deliveries (pending or retrying), deliveries outside the fixed 30-day retention window, and deliveries whose endpoint or frozen config version has been deleted return 409. A replayed exhausted delivery retains its attempt history, so if the replay attempt fails retryably it may exhaust again immediately: replay grants a fresh attempt, not a fresh retry budget.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The webhook delivery ID."},"required":true,"description":"The webhook delivery ID.","name":"id","in":"path"}],"responses":{"200":{"description":"Delivery reset to pending for a fresh attempt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDelivery"}}}},"402":{"description":"The board's plan does not include webhooks (`plan_upgrade_required`). Webhooks require a paid plan, Starter and above.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing webhooks.manage or a family read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Delivery not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Cannot replay: delivery is still open, its 30-day replay window expired, or its destination no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Webhooks"],"operationId":"replayWebhookDelivery"}},"/analytics/apply-clicks":{"get":{"summary":"Get apply clicks by job and first-touch channel","description":"Paginated apply-click counts grouped by job and first-touch channel (ADR-0029). Each apply click is attributed to the session’s first pageview: UTM medium/source when present, otherwise the referrer. This is apply clicks, not confirmed applications, and not last-click. LinkedIn and other in-app browsers often bucket as `direct`. Inclusive UTC `start`/`end` (YYYY-MM-DD) so scheduled pulls can be incremental; defaults to the last 30 completed UTC days ending yesterday. Max range 366 days. Page with `limit` (1–1000, default 100) and `cursor`. Join `jobId` to `GET /v1/jobs/export` `id`, or `companySlug` + `jobSlug` to export `company_slug` + `slug`. Job-detail visitor counts use `GET /v1/analytics/job-visitors` (slug join). Requires `analytics.read`.","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":1000,"description":"Page size (1–1000). Defaults to 100. Not a board-wide top-N cap."},"required":false,"description":"Page size (1–1000). Defaults to 100. Not a board-wide top-N cap.","name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque page cursor from the previous `nextCursor`."},"required":false,"description":"Opaque page cursor from the previous `nextCursor`.","name":"cursor","in":"query"}],"responses":{"200":{"description":"Apply clicks by job and first-touch channel.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"url":{"type":"string","example":"/v1/analytics/apply-clicks"},"hasMore":{"type":"boolean"},"nextCursor":{"type":"string","nullable":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/AnalyticsJobApplyClick"}},"count":{"type":"integer","description":"Total number of results matching the query."},"limit":{"type":"integer","description":"The page size used for this response."},"offset":{"type":"integer","description":"The number of results skipped before this page."},"gatedCount":{"type":"integer","description":"Jobs hidden behind the candidate paywall for the current viewer; absent or 0 for an entitled viewer."}},"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":["Analytics"],"operationId":"getAnalyticsApplyClicks"}},"/analytics/job-visitors":{"get":{"summary":"Get job-detail visitors by first-touch channel","description":"Paginated unique visitors (sessions) that viewed a job-detail page, grouped by company slug, job slug, and first-touch channel (ADR-0029). First-touch UTM campaign/source/medium are included when the landing href was tagged (empty otherwise). `visitors` counts unique sessions and will always be lower than `views` in the jobs export; the two are not expected to match. Join `companySlug` + `jobSlug` to jobs export `company_slug` + `slug` — unlike `GET /v1/analytics/apply-clicks`, which joins on `jobId` / export `id`. Inclusive UTC `start`/`end` (YYYY-MM-DD) so scheduled pulls can be incremental; defaults to the last 30 completed UTC days ending yesterday. Max range 366 days. Page with `limit` (1–1000, default 100) and `cursor`. Requires `analytics.read`.","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":1000,"description":"Page size (1–1000). Defaults to 100. Not a board-wide top-N cap."},"required":false,"description":"Page size (1–1000). Defaults to 100. Not a board-wide top-N cap.","name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque page cursor from the previous `nextCursor`."},"required":false,"description":"Opaque page cursor from the previous `nextCursor`.","name":"cursor","in":"query"}],"responses":{"200":{"description":"Job-detail visitors by first-touch channel and campaign.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"url":{"type":"string","example":"/v1/analytics/job-visitors"},"hasMore":{"type":"boolean"},"nextCursor":{"type":"string","nullable":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/AnalyticsJobVisitor"}},"count":{"type":"integer","description":"Total number of results matching the query."},"limit":{"type":"integer","description":"The page size used for this response."},"offset":{"type":"integer","description":"The number of results skipped before this page."},"gatedCount":{"type":"integer","description":"Jobs hidden behind the candidate paywall for the current viewer; absent or 0 for an entitled viewer."}},"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":["Analytics"],"operationId":"getAnalyticsJobVisitors"}},"/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/search-console/inspect":{"post":{"operationId":"inspectSearchConsoleUrl","summary":"Inspect a URL in Google Search Console","description":"Returns Google’s complete indexed-version URL Inspection result for a URL inside the Board’s stored reporting coverage. This does not run a live test and does not request indexing.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"inspectionUrl":{"type":"string","maxLength":4096,"format":"uri","description":"Canonical HTTPS Board URL covered by the connected property."},"languageCode":{"type":"string","maxLength":35,"pattern":"^[A-Za-z]{2,8}(?:-[A-Za-z0-9]{1,8})*$","description":"Optional BCP-47 language code, such as en-AU."}},"required":["inspectionUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The indexed-version URL Inspection result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleInspectionResponse"}}}},"403":{"description":"The URL is outside the Board’s reporting coverage.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Search Console is not connected or access was lost.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"URL Inspection quota was reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Google rejected the validated request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Google Search Console is unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Analytics"]}},"/analytics/search-console/query":{"post":{"operationId":"querySearchConsole","summary":"Query Google Search Console performance","description":"Runs a live, finalized Search Analytics query against the Board’s connected Google Search Console property. Uses Google’s request and row shape while enforcing the Board’s stored reporting coverage. Results are top rows and are not exhaustive.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"dimensions":{"type":"array","items":{"type":"string","enum":["country","date","device","page","query","searchAppearance"]},"maxItems":3},"type":{"type":"string","enum":["web","image","video","news","discover","googleNews"]},"dimensionFilterGroups":{"type":"array","items":{"type":"object","properties":{"groupType":{"type":"string","enum":["and"]},"filters":{"type":"array","items":{"type":"object","properties":{"dimension":{"type":"string","enum":["country","device","page","query","searchAppearance"]},"operator":{"type":"string","enum":["contains","equals","notContains","notEquals","includingRegex","excludingRegex"]},"expression":{"type":"string","minLength":1,"maxLength":4096}},"required":["dimension","operator","expression"],"additionalProperties":false},"minItems":1,"maxItems":20}},"required":["groupType","filters"],"additionalProperties":false},"maxItems":1},"aggregationType":{"type":"string","enum":["auto","byPage","byProperty"]},"rowLimit":{"type":"integer","minimum":1,"maximum":25000},"startRow":{"type":"integer","minimum":0,"maximum":250000},"dataState":{"type":"string","enum":["final"]}},"required":["startDate","endDate"],"additionalProperties":false}}}},"responses":{"200":{"description":"Live finalized Search Console performance rows.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleQueryResponse"}}}},"409":{"description":"Search Console is not connected or access was lost.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Google Search Console quota was reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Google rejected the validated request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Google Search Console is unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Analytics"]}},"/analytics/traffic":{"get":{"summary":"Get analytics traffic tables","description":"Typed Board homepage traffic breakdowns: top pages, sources, locations, devices, and first-touch UTM campaigns with apply-click attribution. Sources are normalized referrers (never full URLs). Campaigns are tagged inbound sessions only (utm_campaign / utm_source / utm_medium parsed from the first-touch href), one row per triple; `campaignGroupBy=content` also splits them by utm_content / utm_term. 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"},{"schema":{"type":"string","enum":["campaign","content"],"description":"Grouping for the `campaigns` table. `campaign` (default) groups by utm_campaign, utm_source and utm_medium. `content` also groups by utm_content and utm_term, for per-post attribution, and adds `content` and `term` to each row. Visits and apply clicks are matched on the same values."},"required":false,"description":"Grouping for the `campaigns` table. `campaign` (default) groups by utm_campaign, utm_source and utm_medium. `content` also groups by utm_content and utm_term, for per-post attribution, and adds `content` and `term` to each row. Visits and apply clicks are matched on the same values.","name":"campaignGroupBy","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/{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/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}/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}/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/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. An empty rules array requires at least one nonempty structured filter. 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. The resulting rule must retain at least one card or nonempty structured filter. 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/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/{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 and schedules removal of its ID from every post `authorIds` array on the board (paginated drain). 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/{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/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/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/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/{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 and schedules removal of its ID from every post `tagIds` array on the board (paginated drain). 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"}},"/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"}},"/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/{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"}},"/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"}},"/development-origins":{"get":{"summary":"List development origins","description":"Returns the development origins where board sign-in (OAuth completion and auth-email links) may land while a self-hosted frontend is tested. A development origin is never the board’s public or canonical address.","responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"url":{"type":"string","example":"/v1/development-origins"},"hasMore":{"type":"boolean"},"nextCursor":{"type":"string","nullable":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/DevelopmentOrigin"}}},"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":["Domains"],"operationId":"listDevelopmentOrigins"},"post":{"summary":"Add a development origin","description":"Registers a local or preview origin for board sign-in, for example from a deploy pipeline as each preview is created. Adding an origin that is already registered returns it with 200.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDevelopmentOriginBody"}}}},"responses":{"200":{"description":"The origin was already registered.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevelopmentOrigin"}}}},"201":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevelopmentOrigin"}}}},"400":{"description":"The origin was refused (`development_origins_invalid`); the message says why.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The board already has the maximum number of development origins (`development_origins_limit_reached`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Domains"],"operationId":"createDevelopmentOrigin"}},"/development-origins/{id}":{"delete":{"summary":"Remove a development origin","description":"Removes a development origin. A sign-in already in progress through it fails instead of completing anywhere else.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The development origin ID."},"required":true,"description":"The development origin ID.","name":"id","in":"path"}],"responses":{"204":{"description":"Successful response."},"404":{"description":"Development origin not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Domains"],"operationId":"deleteDevelopmentOrigin"}},"/custom-object-types":{"get":{"operationId":"listCustomObjectTypes","summary":"List custom object types","description":"Lists active custom object types. Pass includeArchived to include archived types. Requires `settings.read`.","parameters":[{"schema":{"type":"string","enum":["true","false"],"default":false},"required":false,"name":"includeArchived","in":"query"}],"responses":{"200":{"description":"Catalog types.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CustomObjectType"}}}}},"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"]},"post":{"operationId":"createCustomObjectType","summary":"Create a custom object type","description":"Creates a catalog type with an immutable key. Requires `settings.manage`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCustomObjectTypeBody"}}}},"responses":{"201":{"description":"Created catalog type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomObjectType"}}}},"400":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Catalog resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A key, external ID, or catalog capacity conflicts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field type is immutable or a removed field is still in use.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Settings"]}},"/custom-object-types/{typeId}/records/import-operations":{"post":{"operationId":"startCustomObjectRecordsImport","summary":"Start a custom object record import","description":"Starts a bounded background import from a JSON records payload up to 10MB. Existing externalId values are updated and restored; other rows are created. Returns an operation whose terminal result includes totalRows, created, updated, failed, and capped row errors. Requires `settings.manage`.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"typeId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartCustomObjectRecordsImportBody"}}}},"responses":{"202":{"description":"A catalog record import operation was started.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationResource"}}}},"400":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Catalog resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A key, external ID, or catalog capacity conflicts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The import payload exceeds 10MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field type is immutable or a removed field is still in use.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Settings"]}},"/custom-object-types/{typeId}":{"get":{"operationId":"getCustomObjectType","summary":"Get a custom object type","description":"Gets one catalog type, including archived types. Requires `settings.read`.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"typeId","in":"path"}],"responses":{"200":{"description":"Catalog type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomObjectType"}}}},"404":{"description":"Catalog resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Settings"]},"patch":{"operationId":"updateCustomObjectType","summary":"Update a custom object type","description":"Updates its name, field definitions, or archived state. Omitted fields are preserved. Existing field types are immutable. Requires `settings.manage`.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"typeId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCustomObjectTypeBody"}}}},"responses":{"200":{"description":"Updated catalog type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomObjectType"}}}},"400":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Catalog resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A key, external ID, or catalog capacity conflicts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field type is immutable or a removed field is still in use.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Settings"]}},"/custom-object-types/{typeId}/records":{"get":{"operationId":"listCustomObjectRecords","summary":"List custom object records","description":"Lists records for a catalog type. Requires `settings.read`.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"typeId","in":"path"},{"schema":{"type":"string","enum":["true","false"],"default":false},"required":false,"name":"includeArchived","in":"query"},{"schema":{"type":"string","maxLength":160},"required":false,"name":"search","in":"query"}],"responses":{"200":{"description":"Catalog records.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CustomObjectRecord"}}}}},"404":{"description":"Catalog resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Settings"]},"post":{"operationId":"createCustomObjectRecord","summary":"Create a custom object record","description":"Creates a record. externalId is unique within the account and catalog type. Requires `settings.manage`.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"typeId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCustomObjectRecordBody"}}}},"responses":{"201":{"description":"Created catalog record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomObjectRecord"}}}},"400":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Catalog resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A key, external ID, or catalog capacity conflicts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field type is immutable or a removed field is still in use.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Settings"]}},"/custom-object-types/{typeId}/records/import":{"post":{"operationId":"importCustomObjectRecords","summary":"Import custom object records","description":"Atomically imports up to 500 records. Rows with an existing externalId are replaced and restored; rows without a matching externalId are created. Requires `settings.manage`.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"typeId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportCustomObjectRecordsBody"}}}},"responses":{"200":{"description":"Import counts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomObjectImportResult"}}}},"400":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Catalog resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A key, external ID, or catalog capacity conflicts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field type is immutable or a removed field is still in use.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Settings"]}},"/custom-object-records/{recordId}":{"get":{"operationId":"getCustomObjectRecord","summary":"Get a custom object record","description":"Gets one catalog record, including archived records. Requires `settings.read`.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"recordId","in":"path"}],"responses":{"200":{"description":"Catalog record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomObjectRecord"}}}},"404":{"description":"Catalog resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Settings"]},"patch":{"operationId":"updateCustomObjectRecord","summary":"Update a custom object record","description":"Updates a record. Omitted fields are preserved; null clears logoUrl or externalId; supplied values replace all stored values; archived toggles archive or restore. Requires `settings.manage`.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"recordId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCustomObjectRecordBody"}}}},"responses":{"200":{"description":"Updated catalog record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomObjectRecord"}}}},"400":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Catalog resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A key, external ID, or catalog capacity conflicts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field type is immutable or a removed field is still in use.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Settings"]}},"/email-domains":{"get":{"summary":"List email sender domains","description":"Returns the custom email sender domain for your board. A board has at most one, so the list holds zero or one item.","responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"url":{"type":"string","example":"/v1/email-domains"},"hasMore":{"type":"boolean"},"nextCursor":{"type":"string","nullable":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/EmailDomain"}}},"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":["Domains"],"operationId":"listEmailDomains"},"post":{"summary":"Add an email sender domain","description":"Registers a custom domain for the board’s outgoing email (job alerts, magic links, receipts, Inbox replies) and returns the DNS records to publish. The setup loop is: create the domain, publish every required record in `dnsRecords` at the DNS provider (DNS-only, not proxied), then call `POST /email-domains/{id}/verify` until `status` is `verified`. Cavuno also re-checks pending domains in the background and emails the board owners when the domain verifies. Until then board email keeps sending from the Cavuno address. Requires an active primary custom domain (see `POST /domains`) and a plan that includes branding removal.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEmailDomainBody"}}}},"responses":{"201":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDomain"}}}},"400":{"description":"The hostname is malformed or is not the primary custom domain or one of its subdomains (`email_domains_invalid_hostname`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The plan does not include custom sender domains (`email_domains_plan_required`; Basic and above).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The board already has a sender domain (`email_domains_already_exists`), or has no active primary custom domain (`email_domains_primary_domain_required`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"The email provider failed or is unavailable (`email_domains_provider_error`). Retry later.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Domains"],"operationId":"createEmailDomain"}},"/email-domains/{id}":{"get":{"summary":"Retrieve an email sender domain","description":"Returns the sender domain with its current status and the DNS records to publish, as of the last check.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The email domain ID."},"required":true,"description":"The email domain ID.","name":"id","in":"path"}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDomain"}}}},"404":{"description":"Email domain not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Domains"],"operationId":"getEmailDomain"},"patch":{"summary":"Update the email sender","description":"Changes the From name or mailbox for a verified sender domain. Requires the `settings.manage` permission, as in the dashboard.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The email domain ID."},"required":true,"description":"The email domain ID.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEmailDomainBody"}}}},"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDomain"}}}},"400":{"description":"The sender name or mailbox is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Email domain not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The domain is not verified yet (`email_domains_not_verified`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Domains"],"operationId":"updateEmailDomain"},"delete":{"summary":"Delete an email sender domain","description":"Removes the sender domain. Board email goes back to the Cavuno address immediately; the DNS records can then be deleted.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The email domain ID."},"required":true,"description":"The email domain ID.","name":"id","in":"path"}],"responses":{"204":{"description":"Successful response."},"403":{"description":"The plan does not include custom sender domains (`email_domains_plan_required`; Basic and above).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Email domain not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"The email provider failed or is unavailable (`email_domains_provider_error`). Retry later.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Domains"],"operationId":"deleteEmailDomain"}},"/email-domains/{id}/verify":{"post":{"summary":"Verify an email sender domain","description":"Checks the domain’s DNS records now and returns the updated domain. Call it after publishing the records in `dnsRecords`; DNS changes can take a few minutes to propagate, so a `pending` or `failed` result right after publishing is normal. If `dnsRecords` was empty, this also retries setting the domain up with the email provider.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The email domain ID."},"required":true,"description":"The email domain ID.","name":"id","in":"path"}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDomain"}}}},"403":{"description":"The plan does not include custom sender domains (`email_domains_plan_required`; Basic and above).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Email domain not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"The email provider failed or is unavailable (`email_domains_provider_error`). Retry later.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Domains"],"operationId":"verifyEmailDomain"}},"/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/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"}},"/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"}},"/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":{"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/{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/{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"}},"/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/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"}},"/integrations/indexing":{"get":{"summary":"Retrieve the indexing configuration","description":"Returns the account's Google Indexing API and IndexNow configuration. The Google Indexing API notifies Google immediately when jobs are published or removed; your site is indexed by Google either way. Always returns a config (the Google Indexing API reads as disabled when never provisioned). Toggle it with `POST /v1/integrations/indexing/toggle-google-indexing-api`.","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-google-indexing-api":{"post":{"summary":"Toggle the Google Indexing API","description":"Enables or disables the Google Indexing API, which notifies Google immediately when jobs are published or removed. Your site is indexed by Google either way; this only speeds up how quickly Google learns about job changes. Enabling runs the same checks as Settings → Indexing in the dashboard, in this order: the board has a primary custom domain; the board is not password protected; the board's Google Cloud project is provisioned (this starts automatically when a custom domain becomes primary); and the board's service account is an Owner of the site in Google Search Console. When Search Console is connected, the service account is added as an Owner automatically. Disabling always succeeds.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IndexingToggleBody"}}}},"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IndexingConfig"}}}},"400":{"description":"`integrations_board_not_configured`: the account has no board.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A prerequisite for enabling is not met. `integrations_indexing_custom_domain_required`: connect a custom domain and set it as primary. `integrations_indexing_password_protected`: remove board password protection. `integrations_indexing_setup_not_ready`: the Google Cloud project is not provisioned yet, or its service account credentials are unusable; `details.provisioningStatus` is the current state (`pending`, `provisioning`, `ready`, `error`, or `null` when setup never started). Start or retry setup from Settings → Indexing. `integrations_indexing_search_console_access_required`: add the service account in `details.serviceAccountEmail` as an Owner of the site in Google Search Console, then retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"`integrations_indexing_verification_failed`: Google did not confirm Search Console access (an unexpected Google response, or Google was unreachable). `details.serviceAccountEmail` is the service account that must be an Owner. Retry later.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Integrations"],"operationId":"toggleGoogleIndexingApi"}},"/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"}},"/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"}},"/job-feeds":{"get":{"summary":"List job feeds","description":"Returns your Board's recurring job feeds, oldest first.","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/job-feeds"},"hasMore":{"type":"boolean"},"nextCursor":{"type":"string","nullable":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/JobFeed"}}},"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":["Job feeds"],"operationId":"listJobFeeds"},"post":{"summary":"Create a job feed","description":"Connects an XML job feed URL (for example an ATS or Indeed-style feed). The URL is fetched once to check it serves XML before it is saved. The first run starts straight away and detects the field mapping; until it finishes the feed is `pending_mapping` and `mapping` is `null`. Poll `GET /job-feeds/{id}`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateJobFeedBody"}}}},"responses":{"201":{"description":"The created job feed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobFeedDetail"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The Board already has its maximum job feeds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The feed URL failed the pre-save check.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many feed URL checks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Job feeds"],"operationId":"createJobFeed"}},"/job-feeds/{id}":{"get":{"summary":"Retrieve a job feed","description":"Returns one job feed with its schedule, last run outcome, and mapping review state.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The job feed ID."},"required":true,"description":"The job feed ID.","name":"id","in":"path"}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobFeedDetail"}}}},"404":{"description":"Job feed not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Job feeds"],"operationId":"getJobFeed"},"patch":{"summary":"Update a job feed","description":"Changes any of the URL, name, schedule, enabled state, job limit, apply-URL attribution, and mapping in one request. A changed URL is checked first. A mapping edit applies from the next run, which starts now.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The job feed ID."},"required":true,"description":"The job feed ID.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateJobFeedBody"}}}},"responses":{"200":{"description":"The updated job feed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobFeedDetail"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Job feed not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A mapping edit before the feed has a mapping.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The new feed URL failed the pre-save check.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many feed URL checks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Job feeds"],"operationId":"updateJobFeed"},"delete":{"summary":"Delete a job feed","description":"Stops pulling the feed. Jobs it already published stay published and are no longer linked to it.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The job feed ID."},"required":true,"description":"The job feed ID.","name":"id","in":"path"}],"responses":{"204":{"description":"Successful response."},"404":{"description":"Job feed not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Job feeds"],"operationId":"deleteJobFeed"}},"/job-feeds/{id}/redetect-mapping":{"post":{"summary":"Re-detect a job feed mapping","description":"Discards the current mapping and detects a fresh one on the next run, which starts now. The feed is returned with `mapping: null` until that run finishes.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The job feed ID."},"required":true,"description":"The job feed ID.","name":"id","in":"path"}],"responses":{"200":{"description":"The job feed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobFeedDetail"}}}},"404":{"description":"Job feed not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Job feeds"],"operationId":"redetectJobFeedMapping"}},"/job-feeds/{id}/runs":{"get":{"summary":"List job feed runs","description":"Returns the runs of one feed, most recent first, with row counts and row errors.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The job feed ID."},"required":true,"description":"The job feed ID.","name":"id","in":"path"},{"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/job-feeds/{id}/runs"},"hasMore":{"type":"boolean"},"nextCursor":{"type":"string","nullable":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/JobFeedRun"}}},"required":["object","url","hasMore","nextCursor","data"]}}}},"400":{"description":"The pagination cursor or query is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Job feed not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Job feeds"],"operationId":"listJobFeedRuns"}},"/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","pending_approval"],"description":"Only return jobs matching the given status. One of `draft`, `published`, `expired`, `archived`, or `pending_approval` (awaiting operator approval). `draft` does not include jobs awaiting approval."},"required":false,"description":"Only return jobs matching the given status. One of `draft`, `published`, `expired`, `archived`, or `pending_approval` (awaiting operator approval). `draft` does not include jobs awaiting approval.","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. Always set `externalId` (the source job URL or ATS requisition ID) so reposts are detected reliably. When the 409 has `details.matched_on: \"application_url\"`, another job on your account uses the same `applicationUrl`; `details.matching_jobs` lists up to 5 of them. If the new job is a different role that shares that application destination (one ATS page or one inbox), retry with `allowSharedApplicationUrl: true`. The retry is a different request body, so send a new `Idempotency-Key` if you used one. `remoteOption` is required, and a `salaryMin` or `salaryMax` requires both `salaryCurrency` and `salaryTimeframe`; a missing one returns `400 validation_bad_request` naming the field.","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` and the check that matched in `details.matched_on` (`application_url`, `external_id`, or `composite_hash`). For `application_url`, `details.matching_jobs` lists up to 5 jobs that use the same application URL or email, each as `{ id, title, status }`; if this is a different role that shares that destination, retry with `allowSharedApplicationUrl: true` (and a new `Idempotency-Key` if you used one). A matching `externalId` or an identical job cannot be overridden.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Jobs"],"operationId":"createJob"}},"/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}/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 an explicit expiry, `null` to clear the explicit expiry, or may be omitted to preserve an existing expiry. An ordinary published job without an explicit expiry receives the board's `defaultJobDurationDays` from its publication time (30 days when unset). Sponsored jobs may have no 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/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"}},"/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},"upgrade":{"$ref":"#/components/schemas/PlanUpgradeHint"}},"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/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"}},"/marketing-permissions":{"get":{"summary":"List marketing consent decisions","description":"Every recorded consent decision on the board, read from the user records. People who have never decided are absent — absence of a record means no consent, never a default. Pages may run short of `limit`; follow `nextCursor` for completeness — `hasMore`, not page length, is the signal. `email` is an exact-match lookup returning at most one item; use it to resolve a provider unsubscribe to a board user.","parameters":[{"schema":{"type":"string","enum":["granted","withdrawn"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","format":"email"},"required":false,"name":"email","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"}],"responses":{"200":{"description":"Consent decisions.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"url":{"type":"string","example":"/v1/marketing-permissions"},"hasMore":{"type":"boolean"},"nextCursor":{"type":"string","nullable":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/MarketingPermission"}}},"required":["object","url","hasMore","nextCursor","data"]}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Key lacks `marketing_permissions.read`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Marketing permissions"],"operationId":"listMarketingPermissions"}},"/marketing-permissions/{id}/withdraw":{"post":{"summary":"Withdraw marketing consent for a board user","description":"Operator-initiated withdrawal (`reason: operator_request`) — the right move when someone asks the operator directly to be removed. `{id}` is the board user id. Idempotent: re-withdrawing changes nothing and emits no event. Emits `marketing_permission.withdrawn` on a real transition.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The consent after the withdrawal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketingPermission"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Key lacks `marketing_permissions.manage`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Board user not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Marketing permissions"],"operationId":"createMarketingPermissionWithdraw"}},"/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"}},"/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":{"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/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"}},"/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 explicit expiry. An ordinary published job then receives the board's `defaultJobDurationDays` from its publication time (30 days when unset); drafts and sponsored jobs may remain without an 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, or the update breaks the board's Job form configuration (`jobs_constraint_violation`). Each field group the request sends (salary, seniority, employment type, work arrangement, office locations, remote eligibility, custom fields) is checked against the updated job; groups it omits are not re-checked. `details.violations` lists each broken rule as `{ code, path, params }`.","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}/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}/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/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"}},"/usage":{"get":{"summary":"Retrieve account usage","description":"Retrieves actionable product capacity and Builder credit usage for your Board. 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"}},"/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"}},"/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"}},"/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/{id}/block":{"post":{"summary":"Block a company","description":"Puts a company on the board-scoped blocklist. Blocking always stops company-vertical backfill and rejects automated sourcing writes that match this company. Two outcomes are available. The default (`remove` omitted or false) keeps the public profile, archives currently published jobs, and still allows non-automated human posts. With `remove: true` the profile, its jobs, and its directory, sitemap, and search entries are removed from the board while the company stays on the blocklist, and every write that resolves to it is rejected (ADR-0124). Idempotent: blocking an already-blocked company succeeds and reports `was_already_blocked: true`, and `remove: true` upgrades an already-blocked company to the removed outcome. The response reports `removed` (the resulting state) and `removal_scheduled` (whether this call started the removal).","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/BlockCompanyBody"}}}},"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlockCompanyResult"}}}},"404":{"description":"Company not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Companies"],"operationId":"createCompanyBlock"}},"/companies/{id}/unblock":{"post":{"summary":"Unblock a company","description":"Removes a company from the board-scoped blocklist. Does not republish jobs archived when the company was blocked. A company that had also been removed from the board comes back as an empty profile — it is visible again but its jobs are not restored, and the response reports `was_removed: true` (ADR-0124). Idempotent: unblocking a company that is not blocked succeeds and reports `was_blocked: false`.","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/UnblockCompanyResult"}}}},"404":{"description":"Company not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Companies"],"operationId":"createCompanyUnblock"}},"/companies/{id}/plan-assignments":{"get":{"summary":"List a company's plan assignments","description":"Lists the plans assigned to a company, active first, then expired and revoked. Use `status=active` for the plans that currently give the company its benefits (for example, the membership that lets it post jobs). Cursor-paginated. Requires `plans.read`.","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},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","enum":["active","expired","revoked"],"description":"Only return assignments in this status."},"required":false,"description":"Only return assignments in this status.","name":"status","in":"query"}],"responses":{"200":{"description":"A page of plan assignments.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"url":{"type":"string","example":"/v1/companies/{id}/plan-assignments"},"hasMore":{"type":"boolean"},"nextCursor":{"type":"string","nullable":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/CompanyPlanAssignment"}}},"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":"listCompanyPlanAssignments"},"post":{"summary":"Assign a plan to a company","description":"Gives a company a membership plan at no charge, the same as **Assign** in the company plan dialog. The plan must be an active membership plan. A company holds one membership at a time: assigning while it has an active membership, or a membership invoice awaiting payment, returns 409 `company_plan_membership_taken`. To charge for the plan, create a plan invoice instead. Accepts an optional `Idempotency-Key` header. Requires `plans.manage`.","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":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCompanyPlanAssignmentBody"}}}},"responses":{"201":{"description":"The new plan assignment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyPlanAssignment"}}}},"400":{"description":"Invalid body, or `expiresAt` is not in the future.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Company or plan not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The plan is archived or not a membership plan (`company_plan_not_assignable`), or the company already has a membership or a membership invoice awaiting payment (`company_plan_membership_taken`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Companies"],"operationId":"createCompanyPlanAssignment"}},"/companies/{id}/plan-assignments/{assignmentId}/revoke":{"post":{"summary":"Revoke a company's plan assignment","description":"Ends an active plan assignment now, the same as **Revoke** in the company plan dialog. The record stays, with `status: revoked`. Revoking an assignment that is already revoked or expired returns it unchanged. Revoking does not cancel a recurring plan invoice. Accepts an optional `Idempotency-Key` header. Requires `plans.manage`.","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":"The plan assignment ID returned by the list or assign call."},"required":true,"description":"The plan assignment ID returned by the list or assign call.","name":"assignmentId","in":"path"}],"responses":{"200":{"description":"The plan assignment after the revoke.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyPlanAssignment"}}}},"404":{"description":"Company or plan assignment not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Companies"],"operationId":"revokeCompanyPlanAssignment"}},"/companies/{id}/plan-invoices":{"get":{"summary":"List a company's plan invoices","description":"Lists the plan invoices issued to a company, newest first. Poll it to see when an invoice is paid: the status becomes `paid` and `assignmentId` names the plan assignment it created. Cursor-paginated. Requires `plans.read`.","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},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"A page of plan invoices.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"url":{"type":"string","example":"/v1/companies/{id}/plan-invoices"},"hasMore":{"type":"boolean"},"nextCursor":{"type":"string","nullable":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/CompanyPlanInvoice"}}},"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":"listCompanyPlanInvoices"},"post":{"summary":"Invoice a company for a plan","description":"Sells a membership plan to a company by invoice, the same as **Generate invoice** in the company plan dialog. Issues a Stripe invoice on the board's connected account, due in 30 days, and returns its `hostedInvoiceUrl`. Cavuno does not send the invoice itself; share the link with the employer. The plan is assigned to the company when the invoice is paid. The plan's own price and, for a subscription plan, its interval set the terms; for a plan without a price, send `amountCents` and `currency`. Send `billingInterval` to make the invoice recur. A company holds one membership at a time, so a company with an active membership or another membership invoice awaiting payment gets 409 `company_plan_membership_taken`. Requires an `Idempotency-Key` header: a retry with the same key returns the first response and never issues a second invoice. Requires `plans.manage`.","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":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCompanyPlanInvoiceBody"}}}},"responses":{"201":{"description":"The issued plan invoice.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyPlanInvoice"}}}},"400":{"description":"Invalid body, a plan without a price and no amount (`company_plan_invoice_amount_required`), or an amount or interval for a plan that sets its own (`company_plan_invoice_terms_fixed`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Company or plan not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Stripe is not connected (`company_plan_invoice_connect_required`), the plan is archived or not a membership plan (`company_plan_not_assignable`), or the company already has a membership or a membership invoice awaiting payment (`company_plan_membership_taken`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Stripe could not confirm the invoice (`company_plan_invoice_stripe_error`). An invoice may still have been issued: list the company's plan invoices before trying again with a new Idempotency-Key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Companies"],"operationId":"createCompanyPlanInvoice"}},"/companies/{id}/plan-invoices/{invoiceId}/cancel":{"post":{"summary":"Cancel a company's plan invoice","description":"Cancels a plan invoice awaiting payment, the same as **Cancel invoice** in the company plan dialog: a recurring invoice stops recurring, the Stripe invoice is voided, and the company can be assigned or invoiced again. Canceling an invoice that is already canceled returns it unchanged. Requires an `Idempotency-Key` header and `plans.manage`.","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":"The plan invoice ID returned by the list or create call."},"required":true,"description":"The plan invoice ID returned by the list or create call.","name":"invoiceId","in":"path"}],"responses":{"200":{"description":"The plan invoice after the cancel.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyPlanInvoice"}}}},"404":{"description":"Company or plan invoice not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The invoice is paid or uncollectible, or is still being issued and can be canceled in a few seconds (`company_plan_invoice_not_cancelable`), or Stripe is not connected (`company_plan_invoice_connect_required`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Stripe could not cancel the invoice (`company_plan_invoice_stripe_error`); try again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Companies"],"operationId":"cancelCompanyPlanInvoice"}},"/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}/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/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/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/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/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"}},"/feedback":{"post":{"security":[{},{"bearerAuth":[]}],"summary":"Report a problem as an AI agent","description":"Agent Feedback Protocol v0.1 (https://trybackloop.com/spec/). Report anything that prevented or complicated a task on Cavuno's API, CLI, MCP server or SDK. Responses use the protocol's own shapes, not the usual error envelope. Bodies over 16384 bytes and unknown fields are rejected. 20 reports per account or visitor every 5 minutes. Never include credentials or personal data; send the report, then continue with your task. Discovery: `/.well-known/agent-feedback`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentFeedbackReport"}}}},"responses":{"202":{"description":"Accepted. A retry with the same `session_id` and content returns the original report.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentFeedbackAccepted"}}}},"400":{"description":"`invalid_json` or `invalid_feedback`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentFeedbackError"}}}},"413":{"description":"`payload_too_large`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentFeedbackError"}}}},"415":{"description":"`unsupported_media_type`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentFeedbackError"}}}},"429":{"description":"`rate_limited`. Wait for `Retry-After` seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentFeedbackError"}}}},"503":{"description":"`rate_limit_unavailable`. Continue with your task.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentFeedbackError"}}}}},"x-audience":"operator","tags":["Agent feedback"],"operationId":"submitAgentFeedback"}},"/webhook-endpoints":{"get":{"summary":"List webhook endpoints","description":"Returns Board-owned webhook endpoints. Secrets are never included.","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"}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"url":{"type":"string","example":"/v1/webhook-endpoints"},"hasMore":{"type":"boolean"},"nextCursor":{"type":"string","nullable":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}}},"required":["object","url","hasMore","nextCursor","data"]}}}},"402":{"description":"The board's plan does not include webhooks (`plan_upgrade_required`). Webhooks require a paid plan, Starter and above.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing webhooks.read or a family read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Webhooks"],"operationId":"listWebhookEndpoints"},"post":{"summary":"Create a webhook endpoint","description":"Creates an enabled Board-owned webhook endpoint and returns the signing secret once. The endpoint immediately receives the selected supported V1 event types. The secret is returned only on the original response and is not replayed by an idempotent retry — recover a lost secret by rotating.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookEndpointBody"}}}},"responses":{"201":{"description":"Endpoint created; secret returned once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointCreated"}}}},"400":{"description":"Invalid URL or event types.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The board's plan does not include webhooks (`plan_upgrade_required`). Webhooks require a paid plan, Starter and above.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing webhooks.manage or a family read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Webhooks"],"operationId":"createWebhookEndpoint"}},"/webhook-endpoints/{id}":{"get":{"summary":"Retrieve a webhook endpoint","parameters":[{"schema":{"type":"string","minLength":1,"description":"The webhook endpoint ID."},"required":true,"description":"The webhook endpoint ID.","name":"id","in":"path"}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"402":{"description":"The board's plan does not include webhooks (`plan_upgrade_required`). Webhooks require a paid plan, Starter and above.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing webhooks.read or a family read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Endpoint not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Webhooks"],"operationId":"getWebhookEndpoint"},"patch":{"summary":"Update a webhook endpoint","description":"Updates URL, event selection, or status (pause/resume). URL or event-type changes create a new immutable configuration version.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The webhook endpoint ID."},"required":true,"description":"The webhook endpoint ID.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookEndpointBody"}}}},"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"402":{"description":"The board's plan does not include webhooks (`plan_upgrade_required`). Webhooks require a paid plan, Starter and above.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing webhooks.manage or a family read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Endpoint not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Webhooks"],"operationId":"updateWebhookEndpoint"},"delete":{"summary":"Retire a webhook endpoint","description":"Soft-retires the endpoint: future live deliveries stop and open deliveries are cancelled, but immutable configuration, destination, and signing material are retained so existing deliveries can still be inspected and manually replayed within the retention window. Retired endpoints are hidden from list/detail reads.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The webhook endpoint ID."},"required":true,"description":"The webhook endpoint ID.","name":"id","in":"path"}],"responses":{"204":{"description":"Retired."},"402":{"description":"The board's plan does not include webhooks (`plan_upgrade_required`). Webhooks require a paid plan, Starter and above.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing webhooks.manage or a family read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Endpoint not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Webhooks"],"operationId":"deleteWebhookEndpoint"}},"/webhook-endpoints/{id}/rotate-secret":{"post":{"summary":"Rotate a webhook endpoint secret","description":"Issues a new signing secret (returned once) and keeps the previous secret verifiable for a bounded overlap window. The secret is returned only on the original response and is not replayed by an idempotent retry — recover a lost secret by rotating.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The webhook endpoint ID."},"required":true,"description":"The webhook endpoint ID.","name":"id","in":"path"}],"responses":{"200":{"description":"Secret rotated; new secret returned once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointCreated"}}}},"402":{"description":"The board's plan does not include webhooks (`plan_upgrade_required`). Webhooks require a paid plan, Starter and above.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing webhooks.manage or a family read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Endpoint not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Webhooks"],"operationId":"rotateWebhookEndpointSecret"}},"/webhook-endpoints/{id}/test":{"post":{"summary":"Send a synthetic test delivery","description":"Sends one unmistakably synthetic signed delivery to the endpoint URL and returns a sanitized outcome. Never copies real domain data.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The webhook endpoint ID."},"required":true,"description":"The webhook endpoint ID.","name":"id","in":"path"}],"responses":{"200":{"description":"Test delivery attempted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookTestDelivery"}}}},"402":{"description":"The board's plan does not include webhooks (`plan_upgrade_required`). Webhooks require a paid plan, Starter and above.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing webhooks.manage or a family read scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Endpoint not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Webhooks"],"operationId":"testWebhookEndpoint"}},"/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"}},"/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"}},"/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}/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"}},"/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"}},"/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/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/{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":{"$ref":"#/components/schemas/SubscriberAlert"}}},"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}/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"}},"/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/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"}},"/candidates/{id}/deactivate":{"post":{"summary":"Deactivate a candidate","description":"Disables sign-in, revokes all sessions, and hides the profile from talent surfaces. Profile and application history are preserved for a later reactivate. Idempotent: an already-deactivated candidate returns 200 with the unchanged detail. Requires `candidates.manage`. The request is idempotent when an `Idempotency-Key` header is supplied.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The candidate id."},"required":true,"description":"The candidate id.","name":"id","in":"path"}],"responses":{"200":{"description":"Candidate deactivated. `deactivatedAt` is set. Sign-in is blocked, sessions are revoked, and the profile is hidden from talent surfaces.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateDetail"}}}},"404":{"description":"Candidate not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Sandbox persona accounts cannot have their lifecycle changed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Candidates"],"operationId":"deactivateCandidate"}},"/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"}},"/employers/{id}/deactivate":{"post":{"summary":"Deactivate an employer","description":"Disables sign-in and revokes all sessions. Company memberships, claims, and jobs are preserved for a later reactivate. Idempotent: an already-deactivated employer returns 200 with the unchanged employer. Requires `employers.manage`. The request is idempotent when an `Idempotency-Key` header is supplied.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The employer id."},"required":true,"description":"The employer id.","name":"id","in":"path"}],"responses":{"200":{"description":"Employer deactivated. `deactivatedAt` is set. Sign-in is blocked and sessions are revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Employer"}}}},"404":{"description":"Employer not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Sandbox persona accounts cannot have their lifecycle changed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Employers"],"operationId":"deactivateEmployer"}},"/employers/{id}/reactivate":{"post":{"summary":"Reactivate an employer","description":"Restores sign-in for a previously deactivated employer. Company memberships, claims, and jobs were preserved by deactivate. Sessions revoked by deactivate stay revoked; the employer signs in again. Idempotent: an already-active employer returns 200 with the unchanged employer. Requires `employers.manage`. The request is idempotent when an `Idempotency-Key` header is supplied.","parameters":[{"schema":{"type":"string","minLength":1,"description":"The employer id."},"required":true,"description":"The employer id.","name":"id","in":"path"}],"responses":{"200":{"description":"Employer reactivated. `deactivatedAt` is `null`. Sign-in is restored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Employer"}}}},"404":{"description":"Employer not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Employers"],"operationId":"reactivateEmployer"}},"/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/{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"}},"/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/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 the direct children of a parent category id. The literal \"null\" is a deprecated alias for `topLevel=true`. Combined with `search`, a page may be short or empty while hasMore is true: keep paging until hasMore is false."},"required":false,"description":"Filter to the direct children of a parent category id. The literal \"null\" is a deprecated alias for `topLevel=true`. Combined with `search`, a page may be short or empty while hasMore is true: keep paging until hasMore is false.","name":"parentId","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"When `true`, return only top-level categories (those with no parent). Cannot be combined with a `parentId` category id."},"required":false,"description":"When `true`, return only top-level categories (those with no parent). Cannot be combined with a `parentId` category id.","name":"topLevel","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/{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/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}/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"}},"/page-content":{"get":{"summary":"Retrieve a page intro","description":"Returns the intro written for one category or location page. Address the page with exactly one of `category` or `place`. An unknown slug is a 404.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Slug of the category page: its slug, an alias, or its board-language slug."},"required":false,"description":"Slug of the category page: its slug, an alias, or its board-language slug.","name":"category","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Slug of the location page: the place's `slug`, `canonicalSlug` or a merged-away alias."},"required":false,"description":"Slug of the location page: the place's `slug`, `canonicalSlug` or a merged-away alias.","name":"place","in":"query"}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageContent"}}}},"404":{"description":"Unknown page, or the page has no intro.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Page content"],"operationId":"getPageContent"},"put":{"summary":"Set a page intro","description":"Sets the intro of one category or location page; the last write wins. The page shows it on page 1 with no filters, and the board's public category and place resolutions return it as `introHtml`. Address the page with exactly one of `category` or `place`. An unknown slug is a 404.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Slug of the category page: its slug, an alias, or its board-language slug."},"required":false,"description":"Slug of the category page: its slug, an alias, or its board-language slug.","name":"category","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Slug of the location page: the place's `slug`, `canonicalSlug` or a merged-away alias."},"required":false,"description":"Slug of the location page: the place's `slug`, `canonicalSlug` or a merged-away alias.","name":"place","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PutPageContentBody"}}}},"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageContent"}}}},"404":{"description":"Unknown page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Page content"],"operationId":"updatePageContent"},"delete":{"summary":"Delete a page intro","description":"Removes the intro of one category or location page. Address the page with exactly one of `category` or `place`. An unknown slug is a 404.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Slug of the category page: its slug, an alias, or its board-language slug."},"required":false,"description":"Slug of the category page: its slug, an alias, or its board-language slug.","name":"category","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Slug of the location page: the place's `slug`, `canonicalSlug` or a merged-away alias."},"required":false,"description":"Slug of the location page: the place's `slug`, `canonicalSlug` or a merged-away alias.","name":"place","in":"query"}],"responses":{"204":{"description":"Deleted, or the page had no intro."},"404":{"description":"Unknown page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-audience":"operator","tags":["Page content"],"operationId":"deletePageContent"}},"/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. `tinybird` is deprecated: first-party Board analytics need no connection and are served live by the `/v1/analytics` endpoints, so connecting it changes nothing."},"required":true,"description":"The reporting provider key. `tinybird` is deprecated: first-party Board analytics need no connection and are served live by the `/v1/analytics` endpoints, so connecting it changes nothing.","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. For Search Console, an account administrator with integration-management permission can also explicitly keep reads restricted to stored Board hostnames or authorize the entire selected Google property.","parameters":[{"schema":{"type":"string","enum":["search_console","adsense","tinybird","stripe","google_analytics"],"description":"The reporting provider key. `tinybird` is deprecated: first-party Board analytics need no connection and are served live by the `/v1/analytics` endpoints, so connecting it changes nothing."},"required":true,"description":"The reporting provider key. `tinybird` is deprecated: first-party Board analytics need no connection and are served live by the `/v1/analytics` endpoints, so connecting it changes nothing.","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. `tinybird` is deprecated: first-party Board analytics need no connection and are served live by the `/v1/analytics` endpoints, so connecting it changes nothing."},"required":true,"description":"The reporting provider key. `tinybird` is deprecated: first-party Board analytics need no connection and are served live by the `/v1/analytics` endpoints, so connecting it changes nothing.","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 payments-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. `tinybird` is deprecated: first-party Board analytics need no connection and are served live by the `/v1/analytics` endpoints, so connecting it changes nothing."},"required":true,"description":"The reporting provider key. `tinybird` is deprecated: first-party Board analytics need no connection and are served live by the `/v1/analytics` endpoints, so connecting it changes nothing.","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"}},"/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/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/connect/onboarding-link":{"post":{"summary":"Create a Stripe Connect onboarding link","description":"Returns a hosted Stripe onboarding URL for the Board's payment connection, creating the connected account first if the Board has none. The URL is single-use and expires within minutes: hand it to a human immediately, then poll `GET /v1/billing/connect` until `acceptingPayments` and `payoutsEnabled` are both true. Calling this again issues a fresh link, so request a new one if the human did not finish in time. When the human finishes or the link expires, Stripe sends them to the Board's payment settings in the dashboard. Sandbox boards use a platform-provisioned test connection and are refused with `sandbox_connect_managed` (409). Requires `plans.manage`.","responses":{"200":{"description":"Onboarding link created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingConnectOnboardingLink"}}}},"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":"createBillingConnectOnboardingLink"}},"/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}/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 plan cannot carry a price: the Board payment connection is not ready, the plan is sold by contact, or it is an assign-only membership.","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"}},"/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"}}}}