Cavuno · Schema

CreateJobBody

Job Board SoftwareArtificial IntelligenceCommunity PlatformsMonetization

Properties

Name Type Description
companyId string 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 string 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, inlin
slug string URL-friendly slug for the job. Auto-generated from `title` when omitted.
employmentType string 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 `cust
customEmploymentType stringnull 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
remoteOption string **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
remotePermits array 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 `
remoteTimezones array Where remote candidates must be timezone-compatible. Each entry mirrors the `remotePermits` shape (`world_region`, `continent`, `region`, `subregion`, `country`) plus `timezone` (specific IANA name wi
remoteSponsorship string Whether the employer sponsors visas for remote candidates. One of `yes`, `no`, or `unknown`.
seniority string Seniority level of the role.
applicationUrl string Where candidates apply. Accepts an HTTPS URL, a `mailto:` URI, or a bare email address (which is normalized to `mailto:` form).
salaryMin numbernull Minimum salary, in `salaryCurrency` units. `null` means not set. When `salaryMin` or `salaryMax` is set, `salaryCurrency` and `salaryTimeframe` are both required; otherwise `400`.
salaryMax numbernull Maximum salary, in `salaryCurrency` units. `null` means not set. When `salaryMin` or `salaryMax` is set, `salaryCurrency` and `salaryTimeframe` are both required; otherwise `400`.
salaryCurrency stringnull Three-letter ISO 4217 currency code for `salaryMin` and `salaryMax`. `null` means not set. Required when `salaryMin` or `salaryMax` is set; optional otherwise.
salaryTimeframe stringnull Period the `salaryMin` and `salaryMax` figures are quoted against. `null` means not set. Required when `salaryMin` or `salaryMax` is set; optional otherwise.
skills array Up to 100 canonical skill slugs from `GET /v1/taxonomies/skills`. Every slug must exist in this account.
categories array Up to 100 canonical category slugs from `GET /v1/taxonomies/categories`. Every slug must exist in this account.
isFeatured boolean Whether the job appears in featured slots on the public board.
expiresAt object 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 boa
publishedAt integer 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
educationRequirements array Required education credentials. Each value is one of `high_school`, `associate_degree`, `bachelor_degree`, `professional_certificate`, `postgraduate_degree`, or `no_requirements`.
experienceMonths integer Minimum required experience, expressed in months.
experienceInPlaceOfEducation boolean If `true`, equivalent experience may substitute for the listed education requirements.
inOfficePeriod string Period denominator for `inOfficeFrequency`.
inOfficeFrequency number How often the candidate must be in-office over `inOfficePeriod`.
officeLocations array 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
externalId stringnull 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 cr
customFieldValues object 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 s
collectionValues object 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
collectionOverrides array 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 reje
title string The job title.
company object
status string 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 transitio
allowSharedApplicationUrl boolean 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 skip
View JSON Schema on GitHub

JSON Schema

cavuno-com-create-job-body-schema.json Raw ↑
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/cavuno-com/json-schema/cavuno-com-create-job-body-schema.json",
  "title": "CreateJobBody",
  "x-generated": "2026-11-04",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/cavuno-com-openapi.json#/components/schemas/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",
        "null"
      ],
      "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
          },
          "code": {
            "type": "string",
            "description": "Ignored on input. Job reads add it to some entries; send it back or leave it out."
          }
        },
        "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",
        "null"
      ],
      "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",
        "null"
      ],
      "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",
        "null"
      ],
      "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",
        "null"
      ],
      "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": "#/$defs/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",
        "null"
      ],
      "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. Keys for fields whose collection is archived are ignored, and their stored selections are kept."
    },
    "collectionOverrides": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/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": "#/$defs/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,
  "$defs": {
    "InlineCompanyInput": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 120,
          "description": "The company's display name."
        },
        "website": {
          "type": [
            "string",
            "null"
          ],
          "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",
            "null"
          ],
          "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."
    },
    "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"
      ]
    },
    "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
        }
      ]
    }
  }
}

Work with this as data

Every JSON Schema here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for schemas

4 MCP tools reach this
  • find_json_schemasBrowse and filter every JSON Schema in the catalog.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This JSON Schema
curl "https://apis.io/api/v1/json-schemas/cavuno-com-create-job-body"
All schemas
curl "https://apis.io/api/v1/json-schemas?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.