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

# Stream a saved feed

> Jobs of a feed saved in the Jobo portal's **Feed Builder**. The feed's
rules decide what is in it: its base (every company, your Managed Job
Scraping companies, or a list), its company conditions (ATS, industry,
category, size, revenue, staffing agency), its job conditions (work
model, employment type, experience level, language, category,
occupation, location, posted within) and its always-included and
excluded companies. Edit them in the portal; the request carries only
paging. Requires a customer API key of the account that owns the feed.

Same batch shape, order and cursor semantics as `POST /api/jobs/feed`
with `stable_scan`: oldest first by `created_at`, and the first page
carries `estimated_total`. The cursor fixes the scan's `updated_after`,
batch size and "posted within" window; a continuation may reduce
`batch_size` but never raise it. Billed like `POST /api/jobs/feed`, per
job returned.

**Feed edits.** Every response carries `feed_revision` (and
`X-Feed-Revision`). Editing the feed mid-scan makes the next page return
`409` with code `feed_changed` and `restart_required: true`: start again
without a cursor. An incremental client should run a full scan when
`feed_revision` differs from the one its last full scan used.

**`updated_after`** returns jobs created, updated or re-indexed on or
after the time, plus every job of a company that joined the feed on or
after it (as on the managed feed).




## OpenAPI

````yaml /openapi.yaml post /api/jobs/feed/{feed_id}
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
paths:
  /api/jobs/feed/{feed_id}:
    post:
      tags:
        - Feed
      summary: Stream a saved feed
      description: |
        Jobs of a feed saved in the Jobo portal's **Feed Builder**. The feed's
        rules decide what is in it: its base (every company, your Managed Job
        Scraping companies, or a list), its company conditions (ATS, industry,
        category, size, revenue, staffing agency), its job conditions (work
        model, employment type, experience level, language, category,
        occupation, location, posted within) and its always-included and
        excluded companies. Edit them in the portal; the request carries only
        paging. Requires a customer API key of the account that owns the feed.

        Same batch shape, order and cursor semantics as `POST /api/jobs/feed`
        with `stable_scan`: oldest first by `created_at`, and the first page
        carries `estimated_total`. The cursor fixes the scan's `updated_after`,
        batch size and "posted within" window; a continuation may reduce
        `batch_size` but never raise it. Billed like `POST /api/jobs/feed`, per
        job returned.

        **Feed edits.** Every response carries `feed_revision` (and
        `X-Feed-Revision`). Editing the feed mid-scan makes the next page return
        `409` with code `feed_changed` and `restart_required: true`: start again
        without a cursor. An incremental client should run a full scan when
        `feed_revision` differs from the one its last full scan used.

        **`updated_after`** returns jobs created, updated or re-indexed on or
        after the time, plus every job of a company that joined the feed on or
        after it (as on the managed feed).
      operationId: getSavedJobFeed
      parameters:
        - name: feed_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
          description: The feed's id, shown in the portal's Feed Builder.
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SavedJobFeedRequest'
      responses:
        '200':
          description: Batch of jobs from the saved feed with cursor for next page
          headers:
            X-Has-More:
              schema:
                type: boolean
              description: Duplicates response body `has_more` for quick checks.
            X-Feed-Revision:
              schema:
                type: integer
              description: Duplicates response body `feed_revision`.
            X-Credits-Deducted:
              schema:
                type: integer
              description: >-
                Credits charged to the wallet for this response. `0` when
                included jobs cover every delivered job; absent when the
                Unlimited plan covers the product.
            X-Credits-Balance:
              schema:
                type: integer
              description: >-
                Your wallet balance in credits after the charge. Omitted when
                nothing was charged.
            X-Billing-Status:
              schema:
                type: string
                enum:
                  - Failed
                  - Unconfirmed
              description: >-
                Rare best-effort wallet outcome. Do not automatically replay an
                Unconfirmed delivery.
            X-Quota-Limit:
              schema:
                type: integer
              description: >-
                Your plan's total included jobs across Search, Feed, Export, and
                Outbound.
            X-Quota-Remaining:
              schema:
                type: integer
              description: Included jobs remaining after this response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SavedJobFeedResponse'
        '400':
          description: |
            Invalid request — batch_size out of range, a cursor that is
            malformed or belongs to another feed (restart without it), or a
            feed that resolves to more than 20,000 companies.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          description: |
            The credential is valid but is not a customer API key (master,
            sandbox or marketplace key). Saved feeds require a customer API key
            of the account that owns the feed.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '404':
          description: No feed with this id belongs to your account.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '409':
          description: |
            Code `feed_changed`: the feed was edited since the scan started.
            The problem carries `restart_required: true` and the current
            `feed_revision`. Discard the cursor and start a new scan.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/ServerError'
        '503':
          description: |
            Feed search backend temporarily unavailable. 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: >
            # The feed's rules live in the portal; the request carries only
            paging.

            curl -X POST
            "https://connect.jobo.world/api/jobs/feed/3f2a8c1e-7b0d-4b6a-9a51-0c2f5d9e8b11"
            \
              -H "X-Api-Key: $JOBO_API_KEY" \
              -H "Content-Type: application/json" \
              -d '{"batch_size": 1000}'

            # Continuation requests carry the previous response's cursor.

            curl -X POST
            "https://connect.jobo.world/api/jobs/feed/3f2a8c1e-7b0d-4b6a-9a51-0c2f5d9e8b11"
            \
              -H "X-Api-Key: $JOBO_API_KEY" \
              -H "Content-Type: application/json" \
              -d '{"cursor": "eyJ2IjoxLCJ..."}'
components:
  schemas:
    SavedJobFeedRequest:
      type: object
      description: |
        Cursor-paginated export request for a saved feed. The feed's rules,
        edited in the Jobo portal, decide what is in it; only pagination, the
        incremental watermark and the description format are set per request.
      properties:
        cursor:
          type: string
          nullable: true
          description: >
            Opaque cursor from `next_cursor`. Omit on the first request. The

            cursor embeds the feed's revision, the batch size and

            `updated_after`, so those values sent alongside it are ignored —

            except `batch_size`, which a continuation may reduce but never
            raise.
        batch_size:
          type: integer
          default: 1000
          minimum: 1
          maximum: 1000
        updated_after:
          type: string
          format: date-time
          nullable: true
          description: |
            Only return jobs created, updated or re-indexed on or after this UTC
            timestamp — incremental watermark for syncs — plus every job of a
            company that joined the feed on or after it. Ignored on
            continuations.
        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.
    SavedJobFeedResponse:
      type: object
      required:
        - jobs
        - next_cursor
        - has_more
        - feed_id
        - feed_revision
      properties:
        jobs:
          type: array
          items:
            $ref: '#/components/schemas/JobDto'
        next_cursor:
          type: string
          nullable: true
        has_more:
          type: boolean
        estimated_total:
          type: integer
          format: int64
          nullable: true
          description: |
            Estimated number of jobs the scan will deliver. Present on the
            first page of a scan only; null on continuation pages.
        feed_id:
          type: string
          format: uuid
        feed_revision:
          type: integer
          description: |
            The feed's revision this page was read at. When it differs from the
            one your last full scan used, the feed was edited: run a full scan.
    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'
    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
        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
    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
    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'
    PaymentRequired:
      description: |
        Your remaining included jobs plus your wallet balance cannot cover the
        requested worst-case delivery. Top up your wallet to continue. Credits
        are the wallet's wire unit — 1,000 credits = $1.00.

        The body is plain JSON whose `error` value `"Insufficient credits"` is
        a stable match key; the `detail` sentence may be reworded at any time.
        For example: `{"error": "Insufficient credits", "detail": "This
        request needs 75 credits ($0.075). Your wallet balance is 12 credits
        ($0.012). Top up your wallet to continue.", "group": "JobSearch",
        "credits_required": 75, "credits_balance": 12, "quota_remaining": 10,
        "cost_per_request_usd": 0.075}`.
      headers:
        X-Credits-Required:
          description: Credits the request needs beyond your remaining included jobs.
          schema:
            type: integer
            format: int64
        X-Credits-Balance:
          description: Your current wallet balance in credits.
          schema:
            type: integer
            format: int64
        X-Quota-Remaining:
          description: Included jobs remaining, when a Job Search plan applies.
          schema:
            type: integer
            format: int64
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
        application/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.