Endpoints / List companies

List companies

Search company profiles by name, industry, HQ country, size, headcount, and hiring status.

GET/v1/companies
GEThttps://api.hyperjobs.io/v1/companies

Searches company profiles. Filter by name substring, industry, HQ country, size bucket, headcount range, and whether the company has a live job — with a real total and offset paging. (An early draft of this API made this a browse endpoint with a single limit parameter and no way past its top 200; that limitation never shipped.)

curl -H "Authorization: Bearer $HYPERJOBS_KEY" \
  "https://api.hyperjobs.io/v1/companies?industry=Software%20Development&country=DE&has_jobs=true"

Query parameters#

q
string

Case-insensitive substring match on company name. q=data matches "Databricks" and "Big Data GmbH" alike.

industry
string

LinkedIn industry (exact, case-insensitive), comma = OR. An open vocabulary, not an enum — read values off company.industry rather than guessing.

country
string

HQ country — full name or ISO-2, comma = OR. Filters hq.country, which stores ISO-2 codes, so country=US,DE is the dependable form.

size
string

Size bucket, comma = OR — e.g. 11-50 employees. Matches size_range exactly.

employee_count_gte
integer

Minimum employee count (inclusive).

employee_count_lt
integer

Maximum employee count (exclusive).

has_jobs
boolean

true → only companies with at least one live job in the pool.

limit
integerdefault: 50

Results per page (default 50, max 200, min 1). An out-of-range or non-numeric value is a 400 — nothing is clamped or coerced anymore.

offset
integerdefault: 0

Results to skip. Max 100000.

Unknown parameters are rejected with a 400 that names the parameter — a typo'd filter can no longer masquerade as an empty (or unfiltered) result.

Response#

{ data, total, limit, offset }. total is the full match count across the dataset, not the page size, and every company carries jobs_count — its live (non-duplicate, non-expired) openings.

Response
{
  "data": [
    {
      "slug": "linear",
      "name": "Linear",
      "domain": "linear.app",
      "website": "https://linear.app",
      "logo": "https://media.licdn.com/dms/image/…",
      "industry": "Software Development",
      "type": "Privately Held",
      "description": "Linear is a purpose-built tool for planning and building products…",
      "slogan": "The issue tracking tool you'll enjoy using",
      "specialties": ["issue tracking", "project management", "developer tools"],
      "employee_count": 120,
      "size_range": "51-200",
      "followers": 48210,
      "founded_year": 2019,
      "hq": {
        "country": "US",
        "region": "California",
        "locality": "San Francisco",
        "raw": "San Francisco, California, United States"
      },
      "funding": { "rounds": 4, "last_round_type": "Series B", "…": "…" },
      "stock": null,
      "affiliated_companies": [],
      "data_tier": "remco",
      "jobs_count": 12,
      "updated_at": "2026-07-02T09:14:33.000Z"
    }
  ],
  "total": 158545,
  "limit": 50,
  "offset": 0
}

Each element is a full Company object. There is no next_cursor here — companies page by offset (max 100000), unlike /v1/jobs, which also offers cursor pagination.

Companies through jobs#

The other direction works too. /v1/jobs has company-axis filters — company_industry, company_size, employee_count_gte/lt, funding_gte/lt, company_country, domain — so "remote Rust roles at sub-500-person companies" is one jobs query, no company call involved. Use those when the question is about jobs; use this endpoint when the question is about the companies themselves. Company data walks through both routes.

Sort order#

Fixed, not configurable, and applied after your filters:

  1. data_tier remco first. The richest, verified-tier profiles sort ahead of everything else.
  2. Then followers, descending. Best-known companies first within each group.

A default unfiltered limit=50 still returns 50 heavily-followed remco companies — but with filters and offset you can now reach any of the 158,545, not just the well-known head.

Errors#

StatusCause
400Unknown parameter or invalid value. The body names the param and carries a hint.
401Missing, unknown, or revoked key.
429Rate limit exceeded, or monthly quota spent.
500Server error. Retry with backoff.

Validation is strict: every parameter you send must exist and parse. That's a feature — a misspelled filter is an immediate 400 telling you what to fix, never silently dropped and returning unfiltered results.

Was this page helpful?