# The Stack Jobs API

> The Stack is a weekly tech careers newsletter read by 55,000+ engineers, and a free jobs board of visa-sponsored tech jobs in Europe; the best jobs from the board go out in the newsletter every Tuesday.

- Newsletter: https://www.trythestack.co (subscribe: https://www.trythestack.co/subscribe)
- Jobs board: https://jobs.trythestack.co
- Developer docs (HTML): https://jobs.trythestack.co/developers

## Endpoint

A read-only REST endpoint (Supabase PostgREST) over every active job on The Stack Jobs. No account needed.

- Base URL: `https://cvybaiwpmbqykurtdned.supabase.co/rest/v1/jobs_public`
- Header (required): `apikey: sb_publishable_a61VjughNnWERjT0fMbHZw_JjWvY0ut`
- The key is a publishable key. Row-level security limits it to reading this view, which holds active jobs only.
- Response: a JSON array of rows.

## Columns

| Column | Type | Meaning |
|---|---|---|
| `id` | uuid | Row id. |
| `slug` | text | URL slug: the job page is https://jobs.trythestack.co/jobs/{slug}, its markdown https://jobs.trythestack.co/jobs/{slug}.md. |
| `date_posted` | timestamptz | When the employer posted the job. |
| `title` | text | Job title as the employer wrote it. |
| `organization` | text | Employer name. |
| `category` | text | Job category, when set (often empty). |
| `job_url` | text | The employer's own application page. Applications happen there, not on The Stack. |
| `salary` | text | Salary as stated by the employer: free text, or a JSON MonetaryAmount (currency, value/minValue/maxValue, unitText). Empty when not stated. |
| `employment_type` | text | For example full_time, part_time, contract, internship (spellings vary). |
| `visa_sponsorship` | text | "true" (or "yes"/"1") when the listing offers visa sponsorship; anything else means not stated. |
| `country` | text | Country name in English, for example Germany, United Kingdom. |
| `location` | text | City or place as the listing gives it. |
| `job_description` | text | Full description from the listing. |
| `short_description` | text | One- or two-sentence summary. |
| `experience_level` | text | Years of experience as a band, for example 0-2, 2-5, 10+. |
| `key_skills` | text | Comma-separated skills the listing names. |
| `remote` | text | "remote" or "true" for remote roles, "hybrid" for hybrid; anything else means not marked remote. |

Empty columns mean the listing does not say. Never treat an empty `visa_sponsorship` as "no sponsorship": it means "not stated".

## Filter examples

Filters use [PostgREST operators](https://docs.postgrest.org/en/stable/references/api/tables_views.html#horizontal-filtering) (`eq`, `in`, `ilike`, `gte`, `is`, `not`).

**Remote roles with visa sponsorship**

```
curl 'https://cvybaiwpmbqykurtdned.supabase.co/rest/v1/jobs_public?select=title,organization,country,job_url,slug&remote=in.(remote,true)&visa_sponsorship=in.(true,yes,1)' \
  -H 'apikey: sb_publishable_a61VjughNnWERjT0fMbHZw_JjWvY0ut'
```

**Jobs in Germany, newest first**

```
curl 'https://cvybaiwpmbqykurtdned.supabase.co/rest/v1/jobs_public?select=*&country=eq.Germany&order=date_posted.desc' \
  -H 'apikey: sb_publishable_a61VjughNnWERjT0fMbHZw_JjWvY0ut'
```

**Jobs that name a skill (Python)**

```
curl 'https://cvybaiwpmbqykurtdned.supabase.co/rest/v1/jobs_public?select=title,organization,country,slug&key_skills=ilike.*python*' \
  -H 'apikey: sb_publishable_a61VjughNnWERjT0fMbHZw_JjWvY0ut'
```

**Jobs with a stated salary**

```
curl 'https://cvybaiwpmbqykurtdned.supabase.co/rest/v1/jobs_public?select=title,organization,salary,slug&salary=not.is.null&salary=neq.' \
  -H 'apikey: sb_publishable_a61VjughNnWERjT0fMbHZw_JjWvY0ut'
```

**Posted in the last 7 days (replace the date)**

```
curl 'https://cvybaiwpmbqykurtdned.supabase.co/rest/v1/jobs_public?select=title,organization,country,slug&date_posted=gte.{YYYY-MM-DD}&order=date_posted.desc' \
  -H 'apikey: sb_publishable_a61VjughNnWERjT0fMbHZw_JjWvY0ut'
```

**Title search**

```
curl 'https://cvybaiwpmbqykurtdned.supabase.co/rest/v1/jobs_public?select=title,organization,country,slug&title=ilike.*data%20engineer*' \
  -H 'apikey: sb_publishable_a61VjughNnWERjT0fMbHZw_JjWvY0ut'
```

**Pagination: rows 101–200**

```
curl 'https://cvybaiwpmbqykurtdned.supabase.co/rest/v1/jobs_public?select=title,slug&order=date_posted.desc&limit=100&offset=100' \
  -H 'apikey: sb_publishable_a61VjughNnWERjT0fMbHZw_JjWvY0ut'
```

## Etiquette

- Read-only. Only active listings are in the view; there is no write access.
- Ask for the columns you need with `select=`, and page with `limit` (100–1000) and `offset`.
- Keep to about one request per second, and cache results: new jobs arrive once a day, around 09:00 UTC.
- Link each job to its page on The Stack and send applicants to its `job_url`.

## Other machine-readable files

- [llms.txt](https://jobs.trythestack.co/llms.txt): site brief
- [llms-full.txt](https://jobs.trythestack.co/llms-full.txt): full brief
- [ai.txt](https://jobs.trythestack.co/ai.txt): AI usage policy
- [jobs.md](https://jobs.trythestack.co/jobs.md): every active job, one line each
- [companies.md](https://jobs.trythestack.co/companies.md): every company with open roles
- One job as markdown: `https://jobs.trythestack.co/jobs/{slug}.md`
- One company as markdown: `https://jobs.trythestack.co/companies/{slug}.md`
- [api-catalog.json](https://jobs.trythestack.co/api-catalog.json): endpoint index (also at https://jobs.trythestack.co/.well-known/api-catalog)
- [sitemap.xml](https://jobs.trythestack.co/sitemap.xml)
