> ## Documentation Index
> Fetch the complete documentation index at: https://jobo.world/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Preview the job feed

> Try a `POST /api/jobs/feed` request before you start a scan: the
preview returns how many jobs the feed would deliver and the first
five. It takes the same body as the feed's first request and runs the
same first page — the same filters, validation, `companies`
resolution and `warnings` — so a request that previews cleanly
streams the same jobs. It is not a way to page through the feed:

- `cursor` must be omitted (`400` when present).
- `batch_size`, `stable_scan` and `description_format` are ignored:
  the preview always returns up to 5 jobs of a stable scan, with
  Markdown descriptions.
- Each job is a preview card: its `description` is cut to at most
  500 characters (ending in `…` when cut), and its `summary` is null
  and `qualifications`, `responsibilities` and `benefits` are empty.
  The feed returns them in full.
- The response has no `next_cursor` and no `has_more`.

`estimated_total` is the number of jobs the feed would deliver, as on
the feed's first page. `companies` entries that match no company are
reported in `warnings` (and on `X-Jobo-Warnings`); when no `include`
entry matches, `estimated_total` is `0` and `jobs` is empty.

Previews are free: they are never billed and need no wallet balance.
They count against the same rate limit as `POST /api/jobs/feed`, and
have their own budget of 30 previews per account per hour (`429`
with `Retry-After` past it; JobsFeed subscribers have no such
budget). Retry only `503` (honoring `Retry-After`) and `429`, with
bounded backoff.

To build a request by picking filters, and preview it without an API
key, use the [Feed Builder](https://jobo.world/api/feed-builder) on
jobo.world.




## OpenAPI

````yaml /openapi.yaml post /api/jobs/feed/preview
openapi: 3.0.3
info:
  title: Jobo Enterprise API
  description: >
    The Jobo Enterprise API provides programmatic access to job listings,
    intelligent search,

    incremental feeds, geocoding services, and callback-driven job applications.

    Auto Apply is coming soon as a generally available product; today it is an

    invite-only beta, and accounts without access receive 403

    auto_apply_not_enabled from create.
  version: '2026-08-31'
  contact:
    name: Jobo Support
    url: https://jobo.world
    email: support@jobo.world
  license:
    name: Proprietary — see terms of service
    url: https://jobo.world/terms
  termsOfService: https://jobo.world/terms
servers:
  - url: https://connect.jobo.world
    description: Production
security:
  - ApiKeyAuth: []
tags:
  - name: Jobs
    description: Search and retrieve job listings
  - name: Feed
    description: Bulk job feeds and expiration tracking
  - name: Companies
    description: Company profiles and company-scoped job listings
  - name: Auto Apply
    description: >-
      Submit job applications through Jobo: a blocking create returns the form's
      typed fields, answers are validated and filled synchronously, and the call
      returns the next step or the result.
  - name: Locations
    description: Geocoding and location services
  - name: Occupations
    description: The occupation taxonomy jobs are classified into
paths:
  /api/jobs/feed/preview:
    post:
      tags:
        - Feed
      summary: Preview the job feed
      description: |
        Try a `POST /api/jobs/feed` request before you start a scan: the
        preview returns how many jobs the feed would deliver and the first
        five. It takes the same body as the feed's first request and runs the
        same first page — the same filters, validation, `companies`
        resolution and `warnings` — so a request that previews cleanly
        streams the same jobs. It is not a way to page through the feed:

        - `cursor` must be omitted (`400` when present).
        - `batch_size`, `stable_scan` and `description_format` are ignored:
          the preview always returns up to 5 jobs of a stable scan, with
          Markdown descriptions.
        - Each job is a preview card: its `description` is cut to at most
          500 characters (ending in `…` when cut), and its `summary` is null
          and `qualifications`, `responsibilities` and `benefits` are empty.
          The feed returns them in full.
        - The response has no `next_cursor` and no `has_more`.

        `estimated_total` is the number of jobs the feed would deliver, as on
        the feed's first page. `companies` entries that match no company are
        reported in `warnings` (and on `X-Jobo-Warnings`); when no `include`
        entry matches, `estimated_total` is `0` and `jobs` is empty.

        Previews are free: they are never billed and need no wallet balance.
        They count against the same rate limit as `POST /api/jobs/feed`, and
        have their own budget of 30 previews per account per hour (`429`
        with `Retry-After` past it; JobsFeed subscribers have no such
        budget). Retry only `503` (honoring `Retry-After`) and `429`, with
        bounded backoff.

        To build a request by picking filters, and preview it without an API
        key, use the [Feed Builder](https://jobo.world/api/feed-builder) on
        jobo.world.
      operationId: previewJobFeed
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/JobFeedRequest'
            examples:
              occupation_and_company:
                summary: US nursing jobs at mid-size and large employers, no agencies
                value:
                  locations:
                    - country: United States
                  job_subcategories:
                    include:
                      - Nursing
                  company_sizes:
                    include:
                      - 201-500
                      - 501-1000
                      - 1001-5000
                      - 5001-10000
                      - 10001+
                  company_is_agency: false
      responses:
        '200':
          description: Match count and the first jobs of the feed
          headers:
            X-Jobo-Warnings:
              schema:
                type: string
              description: >-
                When the response has `warnings`: their codes, comma-separated
                (e.g. `companies_unmatched`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobFeedPreviewResponse'
        '400':
          description: >-
            Invalid request: a `cursor`, or any request `POST /api/jobs/feed`
            refuses on its first page — e.g. an unknown `company_sizes` or
            `company_revenues` band, more than 1,000 values in one filter list,
            or occupation filters in an environment where occupations are not
            published.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/ServerError'
        '503':
          description: |
            Feed search backend temporarily unavailable, or (rarely) the
            occupation, company and `exclude_` filters temporarily cannot be
            applied.
            Clients should respect the Retry-After response header (5 seconds)
            before retrying.
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds the client should wait before retrying.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
      x-codeSamples:
        - lang: cURL
          source: >
            # Same body as the first request of POST /api/jobs/feed, without
            cursor.

            curl -X POST "https://connect.jobo.world/api/jobs/feed/preview" \
              -H "X-Api-Key: $JOBO_API_KEY" \
              -H "Content-Type: application/json" \
              -d '{"job_subcategories": {"include": ["Nursing"]}, "company_is_agency": false}'
components:
  schemas:
    JobFeedRequest:
      type: object
      description: |
        Cursor-paginated export request. The cursor preserves the filters and
        batch size from the first request; start a new scan to change them.
      properties:
        locations:
          type: array
          items:
            $ref: '#/components/schemas/LocationFilter'
          nullable: true
        sources:
          type: array
          items:
            type: string
          nullable: true
        work_models:
          type: array
          items:
            type: string
            enum:
              - remote
              - hybrid
              - onsite
          nullable: true
          description: 'Filter by work model: remote, hybrid, onsite. null = all jobs'
        employment_types:
          type: array
          items:
            type: string
            enum:
              - full-time
              - part-time
              - contract
              - internship
              - freelance
              - temporary
          nullable: true
          description: Filter by employment type. null = all jobs
        experience_levels:
          type: array
          items:
            type: string
            enum:
              - intern
              - entry
              - mid
              - senior
              - lead
              - executive
          nullable: true
          description: Filter by experience level. null = all jobs
        languages:
          type: array
          items:
            type: string
          nullable: true
          description: >
            Filter by description language, as ISO 639-1 codes (`en`, `de`,
            `fr`). Language names and locales (`English`, `en-US`) are mapped to
            their code. null = all jobs.
        exclude_sources:
          type: array
          items:
            type: string
          nullable: true
          description: >-
            Leave out jobs from these ATS provider IDs (e.g. `lever`,
            `workday`), normalized like `sources`. May be combined with
            `sources`: `sources: [greenhouse, lever]` with `exclude_sources:
            [lever]` returns Greenhouse jobs.
        exclude_work_models:
          type: array
          items:
            type: string
            enum:
              - remote
              - hybrid
              - onsite
          nullable: true
          description: >-
            Leave out jobs with these work models. Jobs whose work model is
            unknown are kept.
        exclude_employment_types:
          type: array
          items:
            type: string
            enum:
              - full-time
              - part-time
              - contract
              - internship
              - freelance
              - temporary
          nullable: true
          description: >-
            Leave out jobs with these employment types. Jobs whose employment
            type is unknown are kept.
        exclude_experience_levels:
          type: array
          items:
            type: string
            enum:
              - intern
              - entry
              - mid
              - senior
              - lead
              - executive
          nullable: true
          description: >-
            Leave out jobs at these experience levels. Jobs whose experience
            level is unknown are kept.
        exclude_languages:
          type: array
          items:
            type: string
          nullable: true
          description: >-
            Leave out jobs whose description is in these languages, as ISO 639-1
            codes; names and locales are mapped as for `languages`. Jobs whose
            language is unknown are kept.
        companies:
          type: object
          allOf:
            - $ref: '#/components/schemas/InclusionExclusionFilter'
          nullable: true
          description: >-
            Include/exclude companies, resolved exactly as `companies` on `POST
            /api/jobs/search`: each entry is a Jobo company id GUID, a website
            domain or URL (`fedex.com`) matched on the company's stored website
            domain, or anything else a whole company display name (`FedEx`),
            matched case-insensitively after normalization — not a partial
            match.

            Resolved on the first page only: the cursor keeps the company ids
            the entries matched, so a scan's companies are fixed when it starts.
            Entries that match nothing are not a `400`; they come back in the
            first page's `warnings` as `companies_unmatched` (include) or
            `companies_exclude_unmatched` (exclude), and as
            `companies_outside_sources` when the matched companies are on none
            of the requested `sources`. When no include entry matches, or it
            matches only companies outside `sources`, the first page is empty:
            `jobs: []`, `has_more: false`, `next_cursor: null`,
            `estimated_total: 0`, not billed.
        job_categories:
          type: object
          allOf:
            - $ref: '#/components/schemas/InclusionExclusionFilter'
          nullable: true
          description: >-
            Include/exclude filter on the job's occupation category
            (`occupation.category`, e.g. `Healthcare`). Exact, case-insensitive
            match. `GET /api/occupations` lists every value. Jobs without an
            `occupation` never match an include list.
        job_subcategories:
          type: object
          allOf:
            - $ref: '#/components/schemas/InclusionExclusionFilter'
          nullable: true
          description: >-
            Include/exclude filter on the job's occupation subcategory
            (`occupation.subcategory`, e.g. `Nursing`). Exact, case-insensitive
            match. `GET /api/occupations` lists every value.
        occupation_ids:
          type: object
          allOf:
            - $ref: '#/components/schemas/InclusionExclusionFilter'
          nullable: true
          description: >-
            Include/exclude filter on occupation id (`occupation.id`, e.g.
            `esco:8d3e8aaa-791b-4c75-a465-f3f827028f50`). Use ids, not names:
            names can improve between taxonomy releases, ids don't. `GET
            /api/occupations` lists every id.
        industries:
          type: object
          allOf:
            - $ref: '#/components/schemas/InclusionExclusionFilter'
          nullable: true
          description: >-
            Include/exclude filter on the hiring company's industries
            (`company.industries`, e.g. `Software Development`), matched on the
            whole name, case-insensitively. A job matches an include list if its
            company has ANY of the values, and an exclude list if it has none of
            them.
        company_primary_industries:
          type: object
          allOf:
            - $ref: '#/components/schemas/InclusionExclusionFilter'
          nullable: true
          description: >-
            Include/exclude filter on the company's single primary industry
            (`primary_industry` on the company profile, `GET
            /api/companies/{id}`, e.g. `Finance`). Exact, case-insensitive
            match.
        company_categories:
          type: object
          allOf:
            - $ref: '#/components/schemas/InclusionExclusionFilter'
          nullable: true
          description: >-
            Include/exclude filter on the hiring company's business model
            (`categories` on the company profile, `GET /api/companies/{id}`):
            `b2b`, `b2c`, `b2b2c`, `saas`, `marketplace`, `service-provider`. A
            job matches an include list if its company has ANY of them, and an
            exclude list if it has none of them. Case-insensitive.
        company_sizes:
          type: object
          allOf:
            - $ref: '#/components/schemas/CompanySizeBandFilter'
          nullable: true
          description: >-
            Include/exclude filter on the company's headcount band
            (`company_size` on the company profile, `GET /api/companies/{id}`).
            Companies of unknown size never match an include list and are kept
            by an exclude list. An unknown band is a `400`.
        company_revenues:
          type: object
          allOf:
            - $ref: '#/components/schemas/CompanyRevenueBandFilter'
          nullable: true
          description: >-
            Include/exclude filter on the company's annual revenue band
            (`revenue` on the company profile, `GET /api/companies/{id}`).
            Companies of unknown revenue never match an include list and are
            kept by an exclude list. An unknown band is a `400`.
        company_is_agency:
          type: boolean
          nullable: true
          description: >-
            `false` leaves out jobs that recruitment and staffing agencies post
            on behalf of other employers (`is_agency` on the company profile,
            `GET /api/companies/{id}`); `true` returns only theirs. Omit or null
            = all jobs.
        posted_after:
          type: string
          format: date-time
          nullable: true
          description: |
            Return jobs whose employer posting time or first-indexed time is on
            or after this UTC timestamp. Use `updated_after` when edits matter.
        include_reactivated:
          type: boolean
          default: false
          description: |
            Also return jobs that expired and were reactivated (rediscovered
            and re-indexed) on or after `posted_after`. A reactivated job keeps
            its original posting and creation dates, so `posted_after` alone
            never re-delivers it.

            Only changes the `posted_after` filter: it has no effect without
            `posted_after`, and an `updated_after` sync does not need it —
            reactivation re-indexes the job, so `updated_after` already returns
            it. When both `posted_after` and `updated_after` are set, a job
            must match both.
        description_format:
          type: string
          enum:
            - markdown
            - html
          default: markdown
          description: |
            Format of each job's `description`. `markdown` (default) returns it
            as stored. `html` renders it to HTML on the fly: raw HTML in the
            source is escaped and only `http(s)`, `mailto` and relative URLs
            are kept. Read from every request, including cursor continuations.
        updated_after:
          type: string
          format: date-time
          nullable: true
          description: |
            Return jobs created, updated or re-indexed on or after this UTC
            timestamp. Includes jobs that expired and were reactivated in the
            window (reactivation re-indexes the job), so syncs that use
            `updated_after` don't need `include_reactivated`.
        stable_scan:
          type: boolean
          default: true
          description: |
            Page by immutable creation time rather than update recency
            (default). Stable scans cannot skip or duplicate records when jobs
            are updated or deleted mid-scan. Set false explicitly for the
            legacy update-recency ordering.
        cursor:
          type: string
          nullable: true
          description: Opaque cursor from `next_cursor`. Omit on the first request.
        batch_size:
          type: integer
          default: 1000
          minimum: 1
          maximum: 1000
    JobFeedPreviewResponse:
      type: object
      required:
        - estimated_total
        - jobs
      properties:
        estimated_total:
          type: integer
          format: int64
          description: |
            Number of jobs `POST /api/jobs/feed` would deliver for the same
            request, as `estimated_total` on its first page: exact when 1,000
            or fewer jobs match, above that an estimate that can run a few
            percent high. `0` when no `companies.include` entry matches.
        jobs:
          type: array
          maxItems: 5
          description: |
            Up to five jobs the feed's first page starts with, as preview
            cards: each `description` is Markdown, cut to at most 500
            characters; `summary` is null and `qualifications`,
            `responsibilities` and `benefits` are empty.
          items:
            $ref: '#/components/schemas/JobDto'
        warnings:
          type: array
          description: >-
            Non-fatal problems with the request, as on the feed's first page:
            e.g. a `companies` entry that matched no company
            (`companies_unmatched`, `companies_exclude_unmatched`,
            `companies_outside_sources`). Present only when there is something
            to report. The same codes are on the `X-Jobo-Warnings` response
            header, comma-separated.
          items:
            $ref: '#/components/schemas/SearchWarning'
    ProblemDetails:
      type: object
      description: Problem Details object returned for error responses.
      properties:
        type:
          type: string
          nullable: true
        title:
          type: string
          nullable: true
        status:
          type: integer
          nullable: true
        detail:
          type: string
          nullable: true
        instance:
          type: string
          nullable: true
        code:
          type: string
          nullable: true
          description: Stable machine-readable code for Auto Apply domain errors.
        api_version:
          $ref: '#/components/schemas/AutoApplyApiVersion'
    LocationFilter:
      type: object
      properties:
        country:
          type: string
          nullable: true
          description: >-
            Country name or ISO country code (e.g. United States, US, USA).
            Case-insensitive; UK is also accepted.
        region:
          type: string
          nullable: true
        city:
          type: string
          nullable: true
    InclusionExclusionFilter:
      type: object
      properties:
        include:
          type: array
          items:
            type: string
          nullable: true
          description: Values to include (matched case-insensitively)
        exclude:
          type: array
          items:
            type: string
          nullable: true
          description: Values to exclude (matched case-insensitively)
    CompanySizeBandFilter:
      type: object
      description: >-
        Include/exclude filter on company headcount bands (matched
        case-insensitively).
      properties:
        include:
          type: array
          items:
            type: string
            enum:
              - 1-10
              - 11-50
              - 51-200
              - 201-500
              - 501-1000
              - 1001-5000
              - 5001-10000
              - 10001+
          nullable: true
          description: Bands to include. A job matches if its company is in ANY of them.
        exclude:
          type: array
          items:
            type: string
            enum:
              - 1-10
              - 11-50
              - 51-200
              - 201-500
              - 501-1000
              - 1001-5000
              - 5001-10000
              - 10001+
          nullable: true
          description: Bands to exclude.
    CompanyRevenueBandFilter:
      type: object
      description: >-
        Include/exclude filter on company annual revenue bands (matched
        case-insensitively).
      properties:
        include:
          type: array
          items:
            type: string
            enum:
              - under-1m
              - 1m-10m
              - 10m-50m
              - 50m-100m
              - 100m-200m
              - 200m-1b
              - over-1b
          nullable: true
          description: Bands to include. A job matches if its company is in ANY of them.
        exclude:
          type: array
          items:
            type: string
            enum:
              - under-1m
              - 1m-10m
              - 10m-50m
              - 50m-100m
              - 100m-200m
              - 200m-1b
              - over-1b
          nullable: true
          description: Bands to exclude.
    JobDto:
      type: object
      required:
        - id
        - title
        - normalized_title
        - company
        - description
        - language
        - summary
        - listing_url
        - apply_url
        - locations
        - compensation
        - employment_type
        - workplace_type
        - experience_level
        - source
        - created_at
        - updated_at
        - date_posted
        - valid_through
        - qualifications
        - responsibilities
        - benefits
        - is_work_auth_required
        - is_h1b_sponsor
        - is_clearance_required
      properties:
        id:
          type: string
          format: uuid
        external_id:
          type: string
          nullable: true
          description: >-
            Collected ATS or job-board job identifier. Not necessarily an
            employer requisition number or globally unique. Omitted when
            unavailable.
          example: '000123'
        title:
          type: string
        normalized_title:
          type: string
          nullable: true
        occupation:
          type: object
          allOf:
            - $ref: '#/components/schemas/JobOccupationDto'
          nullable: true
          description: The job's occupation. Null when the job is not classified.
        company:
          $ref: '#/components/schemas/JobCompanyDto'
        description:
          type: string
          description: |
            Full job description. Markdown by default; HTML when the request
            sets `description_format` to `html`.
        language:
          type: string
          nullable: true
          description: >-
            Language the description is written in, as a lowercase ISO 639-1
            code. Null when it could not be determined.
          example: en
        summary:
          type: string
          nullable: true
        listing_url:
          type: string
        apply_url:
          type: string
        locations:
          type: array
          items:
            $ref: '#/components/schemas/JobLocationDto'
        compensation:
          type: object
          allOf:
            - $ref: '#/components/schemas/JobCompensationDto'
          nullable: true
          description: |
            Compensation as published by the employer. USD annualization is
            used for salary filters but is not returned in this object.
        employment_type:
          type: string
          nullable: true
          enum:
            - Full-time
            - Part-time
            - Contract
            - Internship
            - Freelance
            - Temporary
        workplace_type:
          type: string
          nullable: true
          enum:
            - Remote
            - Hybrid
            - On-site
        experience_level:
          type: string
          nullable: true
          enum:
            - Intern
            - Entry Level
            - Mid Level
            - Senior
            - Lead
            - Executive
        source:
          type: string
          example: greenhouse
          description: |
            ATS provider identifier. This remains an open string so newly
            supported providers do not break generated clients.
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        date_posted:
          type: string
          format: date-time
          nullable: true
        valid_through:
          type: string
          format: date-time
          nullable: true
        qualifications:
          $ref: '#/components/schemas/JobQualificationsDto'
        responsibilities:
          type: array
          items:
            type: string
        benefits:
          type: array
          items:
            type: string
        is_work_auth_required:
          type: boolean
          nullable: true
        is_h1b_sponsor:
          type: boolean
          nullable: true
        is_clearance_required:
          type: boolean
          nullable: true
    SearchWarning:
      type: object
      description: A non-fatal problem with an otherwise successful request.
      properties:
        code:
          type: string
          description: >-
            Stable machine-readable code. One of `companies_unmatched`,
            `companies_exclude_unmatched`, `companies_outside_sources`,
            `unknown_request_fields` (body fields on `POST /api/jobs/search`, or
            query parameters on `GET /api/jobs`, that the API does not recognise
            and ignored).
          example: companies_unmatched
        field:
          type: string
          nullable: true
          description: The request field the warning is about.
          example: companies.include
        message:
          type: string
          description: Human-readable explanation, safe to show an end user.
    AutoApplyApiVersion:
      type: string
      description: Version of the profileless Auto Apply API contract.
      enum:
        - '2026-08-31'
      example: '2026-08-31'
    ApiRateLimitError:
      type: object
      description: API-key request-window rejection returned by rate-limit middleware.
      required:
        - error
        - detail
        - group
        - retry_after_seconds
      properties:
        error:
          type: string
          example: Rate limit exceeded
        detail:
          type: string
        group:
          type: string
          example: AutoApply
        retry_after_seconds:
          type: integer
          minimum: 0
          nullable: true
    JobOccupationDto:
      type: object
      description: |
        What kind of job this is: one occupation and its place in the
        category › subcategory › occupation taxonomy (see
        `GET /api/occupations`). Null when the job is not classified. The
        employer's own title stays in `title` and `normalized_title`, and
        seniority in `experience_level`.
      required:
        - id
        - name
        - category
        - subcategory
        - isco_code
        - onet_soc_codes
      properties:
        id:
          type: string
          description: |
            Stable taxonomy id: `esco:<uuid>` for an ESCO occupation, or
            `jobo:<slug>` for one Jobo added. Filter and store on this.
          example: esco:8d3e8aaa-791b-4c75-a465-f3f827028f50
        name:
          type: string
          description: Display name. May improve over time; the `id` does not change.
          example: Registered Nurse
        category:
          type: string
          description: Top level of the taxonomy; the value `job_categories` filters on.
          example: Healthcare
        subcategory:
          type: string
          description: >-
            Second level of the taxonomy; the value `job_subcategories` filters
            on.
          example: Nursing
        isco_code:
          type: string
          nullable: true
          description: ISCO-08 unit group.
          example: '2221'
        onet_soc_codes:
          type: array
          items:
            type: string
          description: |
            O\*NET-SOC 2019 codes; the first seven characters are the SOC 2018
            code. Usually one, several where O\*NET splits the occupation, and
            empty when O\*NET has no equivalent.
          example:
            - 29-1141.00
    JobCompanyDto:
      type: object
      required:
        - id
        - name
        - website
        - logo_url
        - summary
        - industries
        - categories
        - linkedin_url
        - crunchbase_url
        - details_url
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        website:
          type: string
          nullable: true
        logo_url:
          type: string
          nullable: true
        summary:
          type: string
          nullable: true
        industries:
          type: array
          items:
            type: string
          description: Industry tags describing what the company does.
        categories:
          type: array
          items:
            type: string
          description: Business-model bucket tags (b2b / b2c / saas / service-provider).
        linkedin_url:
          type: string
          nullable: true
        crunchbase_url:
          type: string
          nullable: true
        details_url:
          type: string
          nullable: true
          description: >
            Direct Jobo API URL to the full company profile endpoint

            (`GET https://connect.jobo.world/api/companies/{id}`).

            RapidAPI consumers should rebuild `/api/companies/{id}` on their

            marketplace gateway instead of following this URL with a RapidAPI
            key.
    JobLocationDto:
      type: object
      required:
        - location
        - city
        - region
        - country
        - latitude
        - longitude
      properties:
        location:
          type: string
          nullable: true
        city:
          type: string
          nullable: true
        region:
          type: string
          nullable: true
        country:
          type: string
          nullable: true
        latitude:
          type: number
          format: double
          nullable: true
        longitude:
          type: number
          format: double
          nullable: true
    JobCompensationDto:
      type: object
      required:
        - min
        - max
        - currency
        - period
      properties:
        min:
          type: number
          format: decimal
          nullable: true
        max:
          type: number
          format: decimal
          nullable: true
        currency:
          type: string
          nullable: true
        period:
          type: string
          nullable: true
          enum:
            - hourly
            - daily
            - weekly
            - monthly
            - yearly
            - per-diem
    JobQualificationsDto:
      type: object
      required:
        - must_have
        - preferred
      properties:
        must_have:
          $ref: '#/components/schemas/QualificationBucketDto'
        preferred:
          $ref: '#/components/schemas/QualificationBucketDto'
    QualificationBucketDto:
      type: object
      required:
        - education
        - certifications
        - skills
      properties:
        education:
          type: array
          items:
            type: string
        certifications:
          type: array
          items:
            type: string
        skills:
          type: array
          items:
            $ref: '#/components/schemas/QualificationSkillDto'
    QualificationSkillDto:
      type: object
      required:
        - name
        - type
      properties:
        name:
          type: string
        type:
          type: string
          default: hard
  responses:
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    TooManyRequests:
      description: Rate limit exceeded.
      headers:
        Retry-After:
          description: Seconds to wait before retrying.
          schema:
            type: integer
            minimum: 0
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
        application/json:
          schema:
            $ref: '#/components/schemas/ApiRateLimitError'
    ServerError:
      description: Unexpected server error.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-Api-Key
      description: API key provided by Jobo

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.