Live Fetch

Fetch one company job board or one job search from the source right now, with POST /v1/live/{source}.

POST https://api.jobspipe.dev/v1/live/{source}
GET  https://api.jobspipe.dev/v1/live/sources

A live fetch reads one company job board, or runs one search, on the source at the moment you call it, instead of searching postings JobsPipe has already collected. Each job comes back as the same Job object job search returns, so code that reads one reads the other.

Live fetch is available through the JobsPipe actors on Apify for now. A call made with a JobsPipe API key answers 403 with live_not_enabled.

Sources

GET /v1/live/sources lists every source a live fetch can read. Each has a kind:

  • board: the input is one company's job board, as its URL or its bare slug. Greenhouse, Lever, Ashby, Workday and SmartRecruiters are board sources, among others.
  • search: the input is keywords and a location. LinkedIn and Indeed are search sources, among others.
200 OK
{
  "sources": [
    {
      "source": "greenhouse",
      "kind": "board",
      "label": "Greenhouse",
      "examples": ["https://job-boards.greenhouse.io/stripe"]
    },
    {
      "source": "linkedin",
      "kind": "search",
      "label": "LinkedIn",
      "examples": []
    }
  ]
}

Use the source value in the path of POST /v1/live/{source}. Its kind decides which body the call takes.

Request

Board sources

FieldTypeDescription
boardstringRequired. The board's URL (https://job-boards.greenhouse.io/stripe) or its slug (stripe).
max_jobsintegerOptional. The most jobs to return, 1 to 5,000. Default 1,000.
include_descriptionsbooleanOptional. Fetch each job's full description. Default true.
cursorstringOptional. The next_cursor of the previous response, to continue.
curl https://api.jobspipe.dev/v1/live/greenhouse \
  -H "Content-Type: application/json" \
  -d '{ "board": "https://job-boards.greenhouse.io/stripe", "max_jobs": 500 }'

Search sources

FieldTypeDescription
keywordsstring | nullWhat to search for, e.g. "data engineer".
locationstring | nullWhere, e.g. "Berlin, Germany".
posted_within_daysinteger | nullOnly jobs posted in the last N days, 1 to 365.
remoteboolean | nulltrue for remote jobs only; null for no preference.
max_jobsintegerOptional. The most jobs to return, 1 to 1,000. Default 100.
cursorstringOptional. The next_cursor of the previous response, to continue.
curl https://api.jobspipe.dev/v1/live/linkedin \
  -H "Content-Type: application/json" \
  -d '{ "keywords": "data engineer", "location": "Berlin, Germany", "posted_within_days": 7 }'

Some sources cannot apply every filter themselves. They then apply it to the title and location of the jobs they return, so results can be fewer than max_jobs.

Unknown fields are refused, and so is a board body sent to a search source or the other way round.

Response

200 OK
{
  "data": [
    {
      "id": "4f0c2a…",
      "job_title": "Staff Data Engineer",
      "company": "Stripe",
      "company_domain": "stripe.com",
      "date_posted": "2026-10-18T07:30:00+00:00",
      "closed_at": null,
      "ghost_score": null
    }
  ],
  "metadata": {
    "source": "greenhouse",
    "board": "stripe",
    "returned": 1,
    "next_cursor": null
  },
  "errors": []
}
  • data: the jobs, each a full Job object (shortened above).
  • metadata.board: the board's slug as the source knows it; null for a search.
  • metadata.returned: how many jobs are in data.
  • metadata.next_cursor: set when there is more. See paging.
  • errors: problems that did not fail the call. A board that does not exist is a 200 with an empty data and { "code": "board_not_found" } here.

What differs from a stored job

A live job is read once, at the moment of the call, so the fields that come from following a posting over time are empty:

  • closed_at, closed_reason and ghost_score are null.
  • discovered_at, last_seen_at and verified_at are the time of the fetch.
  • status is active.
  • technologies is never present.

Paging

A call finishes within about a minute. A large board or a deep search comes back in parts: while metadata.next_cursor is not null, send the same body again with cursor set to it to get the next part. max_jobs counts across one call, not across the whole board.

Errors

Every error body has an error code to branch on.

StatuserrorMeaning
403live_not_enabledLive fetch is not enabled for this caller.
404unknown_sourceNo live source by that name. See GET /v1/live/sources.
422bad_boardThe board URL or slug is not one this source can read. message says why.
422bad_requestThe body does not fit the source's kind, a field is out of range, or the body is not JSON.
429busyLive capacity is used up for now. Retry after retry_after seconds, also sent as Retry-After.
502upstream_unavailableThe source refused or failed after retries. Safe to retry with backoff.
504timeoutThe fetch did not finish in time. Retry with a smaller max_jobs.

Limits

  • One board or one search per call; up to 5,000 jobs from a board and 1,000 from a search per call.
  • A call is answered within about a minute.
  • Live fetch costs no JobsPipe credits. On Apify, you pay per job returned; a failed or empty fetch costs nothing.

On this page