Jobs

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.

post/jobs

Request

  • Base URL: https://api.cavuno.com/v1
  • URL: https://api.cavuno.com/v1/jobs
  • Auth: HTTP bearer

Request body

companyIdstring

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.

descriptionstring required

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.

slugstring

URL-friendly slug for the job. Auto-generated from title when omitted.

employmentType'full_time' | 'part_time' | 'contract' | 'internship' | 'temporary' | 'volunteer' | 'other'

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.

customEmploymentTypestring nullable

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'on_site' | 'hybrid' | 'remote' required

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).

remoteSponsorship'yes' | 'no' | 'unknown'

Whether the employer sponsors visas for remote candidates. One of yes, no, or unknown.

seniority'entry_level' | 'associate' | 'mid_level' | 'senior' | 'lead' | 'principal' | 'director' | 'executive'

Seniority level of the role.

applicationUrlstring required

Where candidates apply. Accepts an HTTPS URL, a mailto: URI, or a bare email address (which is normalized to mailto: form).

salaryMinnumber nullable

Minimum salary, in salaryCurrency units. null means not set. When salaryMin or salaryMax is set, salaryCurrency and salaryTimeframe are both required; otherwise 400.

salaryMaxnumber nullable

Maximum salary, in salaryCurrency units. null means not set. When salaryMin or salaryMax is set, salaryCurrency and salaryTimeframe are both required; otherwise 400.

salaryCurrencystring nullable

Three-letter ISO 4217 currency code for salaryMin and salaryMax. null means not set. Required when salaryMin or salaryMax is set; optional otherwise.

salaryTimeframe'per_year' | 'per_month' | 'per_week' | 'per_day' | 'per_hour' nullable

Period the salaryMin and salaryMax figures are quoted against. null means not set. Required when salaryMin or salaryMax is set; optional otherwise.

skillsstring[]

Up to 100 canonical skill slugs from GET /v1/taxonomies/skills. Every slug must exist in this account.

categoriesstring[]

Up to 100 canonical category slugs from GET /v1/taxonomies/categories. Every slug must exist in this account.

isFeaturedboolean

Whether the job appears in featured slots on the public board.

publishedAtinteger

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.

educationRequirementsstring[]

Required education credentials. Each value is one of high_school, associate_degree, bachelor_degree, professional_certificate, postgraduate_degree, or no_requirements.

experienceMonthsinteger

Minimum required experience, expressed in months.

experienceInPlaceOfEducationboolean

If true, equivalent experience may substitute for the listed education requirements.

inOfficePeriod'per_week' | 'per_month' | 'per_year'

Period denominator for inOfficeFrequency.

inOfficeFrequencynumber

How often the candidate must be in-office over inOfficePeriod.

externalIdstring nullable

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.

customFieldValuesobject

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.

collectionValuesobject

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.

titlestring required

The job title.

status'draft' | 'published'

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.

allowSharedApplicationUrlboolean

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.

Response

Successful response.

idstring required

Unique identifier for the object. Use this value as the {id} path parameter for the job endpoints (e.g. GET /v1/jobs/{id}).

object'job' required

String representing the object's type. Objects of the same type share the same value.

titlestring required

The job title.

slugstring nullable required

URL-friendly slug used in public board URLs, or null if no slug is set.

status'draft' | 'published' | 'expired' | 'archived' | 'pending_approval' required

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.

companyIdstring nullable required

Identifier of the company the job belongs to, or null if no company is attached.

employmentType'full_time' | 'part_time' | 'contract' | 'internship' | 'temporary' | 'volunteer' | 'other' nullable required

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.

remoteOption'on_site' | 'hybrid' | 'remote' nullable required

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'entry_level' | 'associate' | 'mid_level' | 'senior' | 'lead' | 'principal' | 'director' | 'executive' nullable required

Seniority level of the role, or null if not specified.

salaryMinnumber nullable required

Minimum salary in salaryCurrency units, or null if not specified.

salaryMaxnumber nullable required

Maximum salary in salaryCurrency units, or null if not specified.

salaryCurrencystring nullable required

Three-letter ISO 4217 currency code for the salary range, or null if no salary is specified.

salaryTimeframe'per_year' | 'per_month' | 'per_week' | 'per_day' | 'per_hour' nullable required

Period the salary range is quoted against, or null if no salary is specified.

isFeaturedboolean required

Whether the job appears in featured slots on the public board.

publishedAtstring nullable required

Time at which the job was first published, or null if not yet published. ISO 8601 datetime.

expiresAtstring nullable required

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.

createdAtstring required

Time at which the job was created. ISO 8601 datetime.

updatedAtstring required

Time at which the job was last updated. ISO 8601 datetime.

revisioninteger required

Monotonic Job lifecycle revision used to reconcile webhook events. Legacy rows are 0 until the rollout backfill runs.

skillsstring[] required

Canonical skill slugs assigned to the job.

categoriesstring[] required

Canonical category slugs assigned to the job.

externalIdstring nullable required

External identifier supplied by the caller on create, used for deduplication via GET /v1/jobs?externalId=.... null when no external identifier was set.

customFieldValuesobject required

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.

collectionValuesobject required

Operator-facing collection record IDs keyed by job collection field. Always an object; values are arrays even for single-select fields.

descriptionstring nullable required

Long-form description of the role (HTML), or null if not specified.

applicationUrlstring nullable required

Where candidates apply, or null if not specified. An HTTPS URL or mailto: URI.

remoteWorldwideboolean nullable required

Read-only: derived from remotePermits. true only when the authored selection is a single {type:"worldwide"} entry.

remoteAllowedTzOffsetsnumber[] required

Read-only: derived from remoteTimezones (per-country/per-region offset fan-out). UTC hour offsets used by the job-search index.

remoteWorkPermitCountryCodesstring[] required

Read-only: derived from remotePermits (hierarchical groups fan out to alpha2 sets; subdivisions auto-add the parent country). ISO 3166-1 alpha-2 codes.

remoteWorkPermitSubdivisionCodesstring[] required

Read-only: derived from remotePermits (subdivision entries only). ISO 3166-2 codes.

remoteSponsorship'yes' | 'no' | 'unknown' required

Whether the employer sponsors visas for remote candidates. One of yes, no, or unknown.

educationRequirementsstring[] required

Required education credentials. Each value is one of high_school, associate_degree, bachelor_degree, professional_certificate, postgraduate_degree, or no_requirements.

experienceMonthsnumber nullable required

Minimum required experience in months, or null if not specified.

experienceInPlaceOfEducationboolean nullable required

If true, equivalent experience may substitute for the listed education requirements. null if not specified.

inOfficePeriod'per_week' | 'per_month' | 'per_year' nullable required

Period denominator for inOfficeFrequency, or null if not specified.

inOfficeFrequencynumber nullable required

How often the candidate must be in-office over inOfficePeriod, or null if not specified.

Changes

    • info

      added the optional property / to the response with the status

    • info

      added the optional property / to the response with the status

    • info

      added the optional property / to the response with the status