Search jobs

POST /flan.jobs.v1.JobsService/List

Returns verified jobs matching a free-text query and structured filters. Results are sorted by the sort parameter (relevance-weighted by default when q is provided, newest otherwise).

Parameters

All request fields are optional. Send filters under query.filters using proto3-JSON camelCase field names.

| Field | Type | Default | Description | | ------------------------------- | ------- | ----------- | --------------------------------------------------------------------------------- | | query.query | string | — | Free-text query. ≤ 200 characters. | | query.filters.country | string | — | ISO 3166-1 alpha-2 code (e.g. US, GB, DE). Uppercased. | | query.filters.city | string | — | City name. Matched against city_names. | | query.filters.remote | boolean | — | Filter to remote-only (true) or non-remote (false). | | query.filters.workMode | enum | — | One of remote, hybrid, onsite. | | query.filters.employmentType | string | — | e.g. full_time, part_time, contract, internship, temporary. | | query.filters.company | string | — | Match against company name. | | query.filters.companyId | string | — | Match against the canonical company slug. | | query.filters.seniority | string | — | e.g. intern, junior, mid, senior, lead, staff, manager, director. | | query.filters.salaryMin | integer | — | Jobs with salary_max >= salary_min. | | query.filters.salaryMax | integer | — | Jobs with salary_min <= salary_max. | | query.filters.discoveredAfter | date | — | RFC3339 or YYYY-MM-DD. Jobs first seen at or after. | | query.filters.verifiedAfter | date | — | RFC3339 or YYYY-MM-DD. Jobs last verified at or after. | | query.filters.sort | enum | relevance | One of relevance, newest, recently_verified, salary_desc, company. | | query.limit | integer | 25 | Page size. 1–100. | | query.cursor | string | — | Opaque pagination cursor from pagination.nextCursor. |

Example

curl -X POST "https://api.useflan.app/flan.jobs.v1.JobsService/List" \
  -H "Content-Type: application/json" \
  --data '{"query":{"filters":{"country":"US","workMode":"remote","sort":"recently_verified"},"limit":3}}'
{
  "data": [
    {
      "id": "018f3b21-4b2c-7e3d-9a40-23e8a1f2b3c4",
      "slug": "senior-frontend-engineer-acme",
      "title": "Senior Frontend Engineer",
      "companyName": "Acme",
      "companySlug": "acme",
      "locationText": "Remote, US",
      "remote": true,
      "employmentType": "full_time",
      "seniority": "senior",
      "salary": {
        "min": 140000,
        "max": 180000,
        "currency": "USD",
        "period": "year"
      },
      "snippet": "Build the next generation of our customer dashboard…",
      "sourcePlatform": "greenhouse",
      "discoveredAt": "2026-06-18T14:20:00Z",
      "lastVerifiedAt": "2026-06-21T08:30:00Z"
    }
  ],
  "pagination": { "nextCursor": "eyJwYWdlIjoyfN...", "hasMore": true }
}

Job card fields

| Field | Type | Description | | ---------------- | -------------- | ---------------------------------------------------------------- | | id | uuid | Stable job identifier. | | slug | string | URL slug. May be empty. | | title | string | Job title. | | companyName | string | Display name of the company. | | companySlug | string | URL slug for the company, if known. | | locationText | string | Human-readable location. | | remote | boolean | Whether the role accepts remote applicants. | | employmentType | enum | full_time, part_time, contract, internship, temporary. | | seniority | string | Seniority bucket. | | salary | object | null | { min, max, currency, period }. | | snippet | string | Short description excerpt. | | sourcePlatform | string | ATS platform (e.g. greenhouse). | | discoveredAt | datetime | When the job was first crawled. | | lastVerifiedAt | datetime | When the job was last confirmed active. |

Job cards do not include a per-card status field. The search index only contains active jobs, so all returned cards are implicitly active. Use JobsService.Get for the full status.