Endpoints / Retrieve a company

Retrieve a company

Fetch one company profile by slug — the cheapest path to the full profile when a job or a company search has already handed you the slug.

GET/v1/companies/{slug}
GEThttps://api.hyperjobs.io/v1/companies/{slug}

One company profile by slug. When you already have a slug — off a job or a company search result — this is the cheapest way to the full profile.

curl -H "Authorization: Bearer $HYPERJOBS_KEY" \
  "https://api.hyperjobs.io/v1/companies/linear"

Path parameters#

slug
stringpathrequired

The company's slug, matched exactly. No normalisation beyond URL-decoding — no case-folding, no fuzzy matching, no lookup by name or domain.

Slugs are LinkedIn-style: usually lower-case and hyphenated, and usually recognisable from the company name. "Usually" isn't "always" — see where slugs come from.

No query parameters. The full profile is always returned; there's nothing optional to request.

Where slugs come from#

Don't construct a slug from a company name

Slugs resemble company names often enough to be dangerous. Linearlinear works; the next one you guess won't, and a wrong guess is an indistinguishable 404 rather than a hint.

JS
// Wrong. Works for maybe half of companies, silently 404s for the rest.
const slug = name.toLowerCase().replace(/\s+/g, "-");

Always read the slug from data you were given — and when you only have a name, search for it: /v1/companies?q= does substring name matching and returns the real slug.

Two reliable sources:

SourceHow
A jobjob.company.slug — present on 99.9997% of postings
The search endpoint/v1/companies?q= name search, plus industry, HQ country, and size filters

In practice this endpoint is the second half of a jobs query: filter jobs, take company.slug off a result, fetch the profile.

JS
// The normal flow — the slug comes from the data, never from a string transform.
const { data } = await getJobs({ organization: "linear", limit: 1 });
const slug = data[0]?.company?.slug;
if (slug) {
  const company = await getCompany(slug);
}

A job's company may have no slug

When a posting doesn't resolve to a profile, job.company is a minimal fallback with no slug — and nothing to look up here. Guard it rather than interpolating undefined into the path, which produces a confusing 404 on /v1/companies/undefined.

Response#

The company object itself, not wrapped:

Response
{
  "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",
    "last_round_date": "2022-06-15",
    "last_round_amount_usd": 35000000,
    "total_investment_usd": 52000000,
    "crunchbase_slug": "linear-2",
    "crunchbase_categories": ["Software", "Productivity Tools"]
  },
  "stock": null,
  "affiliated_companies": [],
  "data_tier": "remco",
  "jobs_count": 12,
  "updated_at": "2026-07-02T09:14:33.000Z"
}

This response is not wrapped in `data`

/v1/companies returns { data: [ … ] }. This endpoint returns the company at the top level, matching /v1/jobs/{id}. A shared response handler that reaches for .data gets undefined here.

Every field is documented in the Company object. Three worth re-reading before you build on this payload:

  • hq.country is ISO-2 ("US"), while a job's location.countries are full names (["United States"]). Joining them needs a mapping table.
  • hq, funding, and stock are null when the underlying data is absent — and stock: null is not evidence a company is private.
  • jobs_count is live — the company's non-duplicate, non-expired openings in the pool right now, recomputed roughly every 15 minutes. 0 means not currently hiring, not "no data".

The profile returned here is identical to the one embedded on a job. Fetching it is only worth a request when you have a slug but no job in hand — if you just got the job, you already have the whole company object.

Freshness#

updated_at is when the profile last refreshed, which has nothing to do with job ingestion. A job posted an hour ago routinely carries a company profile that's months old. That's expected — headcount and funding move on their own timescale.

Errors#

StatusCause
401Missing, unknown, or revoked key.
404No company with that slug.
429Rate limit exceeded.
500Server error. Retry with backoff.
404
{ "error": "not found" }

A 404 means no profile has that slug — most often a constructed or misremembered one. It carries no detail, and retrying won't change it: treat it as "no such company" and move on rather than as an error to back off from. To recover, search for the name — /v1/companies?q= — or go back to a jobs query and read the real slug off company.slug.

Was this page helpful?