Cavuno Job feeds API

Recurring XML job feeds pulled from a URL on a schedule: connect, map fields, re-detect, and track runs.

Operations 7

GET /job-feeds List job feeds #
POST /job-feeds Create a job feed #
GET /job-feeds/{id} Retrieve a job feed #
PATCH /job-feeds/{id} Update a job feed #
DELETE /job-feeds/{id} Delete a job feed #
POST /job-feeds/{id}/redetect-mapping Re-detect a job feed mapping #
GET /job-feeds/{id}/runs List job feed runs #

Work with this as data

Every API 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 apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • 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 API
curl "https://apis.io/api/v1/apis/cavuno-com:cavuno-com-job-feeds-api"
All apis
curl "https://apis.io/api/v1/apis?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.

OpenAPI Specification

cavuno-com-job-feeds-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Cavuno v1 REST Job feeds 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. ## Base URL


    Production: `https://api.cavuno.com/v1`


    All API requests must be made over HTTPS. Calls made over plain HTTP will fail. ## Authentication


    The 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. Cavuno 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. Authentication to the API is performed via Bearer auth. Provide your API key as the bearer token in the `Authorization` header:


    ```bash

    curl https://api.cavuno.com/v1/jobs \

    -H "Authorization: Bearer YOUR_SECRET_API_KEY"

    ```


    API requests without authentication will fail. ## Rate limits


    The 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. If you have a use case that needs a higher limit, contact support. ## Idempotency


    The 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. To perform an idempotent request, provide an additional `Idempotency-Key` header on any `POST`, `PATCH`, or `DELETE` request:


    ```bash

    curl https://api.cavuno.com/v1/jobs \

    -X POST \

    -H "Authorization: Bearer cavuno_live_..." \

    -H "Idempotency-Key: $(uuidgen)" \

    -H "Content-Type: application/json" \

    -d ''{ "title": "Senior Engineer" }''

    ```


    ## Errors


    Cavuno 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). Error responses include a JSON body with details:


    ```json

    {

    "error": {

    "code": "validation_bad_request",

    "message": "Field ''title'' is required.",

    "requestId": "req_..."

    }

    }

    ```


    Some errors carry an additional `details` field with structured context, such as per-field validation issues. ### Plan upgrade hints


    When 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:


    ```json

    {

    "error": {

    "code": "settings_plan_required_for_branding_removal",

    "message": "Removing Cavuno branding requires a plan that includes branding removal.",

    "requestId": "req_...",

    "upgrade": {

    "capability": "canRemoveBranding",

    "requiredPlan": "basic",

    "checkout": { "method": "POST", "path": "/v1/billing/checkout" },

    "changePlan": { "method": "POST", "path": "/v1/billing/upgrade" }

    }

    }

    }

    ```


    Call `GET /v1/billing/subscription` first. With no active subscription, use `checkout`; with one, use `changePlan`. Send `{ "planKey": "" }` 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`.'
  contact:
    name: Cavuno
    url: https://cavuno.com
servers:
- url: https://api.cavuno.com/v1
  description: Production
security:
- bearerAuth: []
tags:
- name: Job feeds
  description: 'Recurring XML job feeds pulled from a URL on a schedule: connect, map fields, re-detect, and track runs.'
paths:
  /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
                    - 'null'
                  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
                    - 'null'
                  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
components:
  schemas:
    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
          - 'null'
        applyUrlAttribution:
          $ref: '#/components/schemas/JobFeedApplyUrlAttribution'
        lastRunAt:
          type:
          - string
          - 'null'
        nextRunAt:
          type:
          - string
          - 'null'
          description: When the next pull is due. `null` while the feed is disabled.
        lastError:
          type:
          - string
          - 'null'
        consecutiveFailures:
          type: number
        createdAt:
          type: string
        mapping:
          type:
          - object
          - 'null'
          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
    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
    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
    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
          - 'null'
          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
          - 'null'
          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
    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
          - 'null'
        completedAt:
          type:
          - string
          - 'null'
        createdAt:
          type: string
      required:
      - id
      - object
      - status
      - totalRows
      - processedRows
      - createdCount
      - updatedCount
      - skippedCount
      - errorCount
      - errors
      - startedAt
      - completedAt
      - createdAt
    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
    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.
    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.
    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.'
    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
          - 'null'
        applyUrlAttribution:
          $ref: '#/components/schemas/JobFeedApplyUrlAttribution'
        lastRunAt:
          type:
          - string
          - 'null'
        nextRunAt:
          type:
          - string
          - 'null'
          description: When the next pull is due. `null` while the feed is disabled.
        lastError:
          type:
          - string
          - 'null'
        consecutiveFailures:
          type: number
        createdAt:
          type: string
      required:
      - id
      - object
      - name
      - url
      - status
      - enabled
      - intervalHours
      - expireMissing
      - jobLimit
      - applyUrlAttribution
      - lastRunAt
      - nextRunAt
      - lastError
      - consecutiveFailures
      - createdAt
    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:
              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.
  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.
externalDocs:
  description: Cavuno API reference
  url: https://cavuno.com/docs/api