# Amazon Jobs API

> Query Amazon's postings through one API with ?source=amazon — plus why amazon.jobs' posted_date parses a day early east of Greenwich.

Source: https://hyperjobs.io/ats/amazon

Amazon is not a platform. Every other source on this site is software that hosts
many employers' boards — one [Greenhouse](/ats/greenhouse) adapter reaches every
company that bought Greenhouse. This one reaches Amazon. That's the whole of it.

It's here because Amazon is large enough that its jobs matter on their own, and
because it runs a bespoke careers site rather than buying an ATS, so no platform
adapter will ever find it: there's no `jobs.lever.co/<slug>` to detect, no vendor
fingerprint to match. If you want Amazon's postings, you write an adapter for
Amazon and you own it forever.

We wrote it, and it's ours to own: query it with `?source=amazon`.
[`/v1/meta`](/docs/api-reference/meta) is the authoritative live vocabulary, with
the current count per source.

## How amazon.jobs actually works

Of the bespoke giants, this is the friendly one. Unauthenticated JSON, offset
pagination, full job objects with descriptions inline:

```bash
curl "https://www.amazon.jobs/en/search.json?offset=0&result_limit=100&sort=recent"
```

No token, no handshake, no browser, no N+1. The response carries `hits` for the
total and `jobs` for the page, and you walk `offset` until the batch comes up
short or the total is exhausted.

### What the adapter reads

The description isn't one field. Amazon splits a posting into three, and they have
to be reassembled in order:

```
description  +  <h3>Basic qualifications</h3>basic_qualifications
             +  <h3>Preferred qualifications</h3>preferred_qualifications
```

Read `description` alone and you get the pitch with none of the requirements —
which looks like a populated field, so nothing alerts you. It's the same trap
[Lever](/ats/lever)'s three-part body sets, in a different arrangement.

`job_category` (`"Medical, Health, & Safety"`) and `job_family` (`"Pharmacy"`) are
both consistently filled, giving a department and a finer team grouping with
nothing to infer. The adapter keeps `job_family` only when it differs from the
category, so a row doesn't carry the same string twice.

The id field is called `id_icims` — a fingerprint of what's underneath the careers
site. It's the stable id and the adapter uses it, but nothing else about this API
behaves like a standard iCIMS tenant. Don't read the name as a shortcut.

### The coordinates are hidden inside strings

`locations[]` is an array of **JSON-encoded strings**, not objects. Each has to be
parsed a second time to reach a `"coordinates": "lat,lng"` field inside it. JSON
inside JSON, with unparseable entries skipped rather than thrown.

It's worth the trouble: exact coordinates mean no geocoding, so a location is a
point rather than a string somebody has to resolve into a guess.

## What bites you

<Warning title="`posted_date` parses a day early, and only east of Greenwich">
  Amazon posts bare calendar dates: `May  6, 2026` — often with a double space,
  and with no timezone anywhere.

  `Date.parse` reads a non-ISO date-only string as **local midnight**. On a
  machine in Europe/Rome that makes `May 6, 2026` into `2026-05-05T22:00Z`, and
  every posting reads as a day earlier than it was posted. This was live in
  production on this source. It throws nothing, it looks completely normal, and it
  reproduces only east of Greenwich — so it survives review on any laptop set to
  UTC or US time.

  The fix is to build the date from its parts with `Date.UTC` and never
  `Date.parse` a bare date. ISO date-only strings aren't affected, because the
  spec pins those to UTC — which is exactly why this hides: the common path is
  correct.
</Warning>

**One adapter, one company, forever.** This is the honest cost of a bespoke
source. When Amazon reshapes `search.json`, nothing else in your pipeline notices
and nothing else covers the gap. Multiply that by every giant you want and you see
the shape of the problem. Same deal as [Apple](/ats/apple), [Uber](/ats/uber),
[TikTok](/ats/tiktok), [Google](/ats/google), [Microsoft](/ats/microsoft) and
[IBM](/ats/ibm).

**There's no salary.** Nothing structured. Whatever comp appears is prose inside
the qualifications HTML.

**A missing `job_path` means no URL.** Rows without one are dropped rather than
guessed at, since the posting URL is built from it.

## Or use ours

The fetch is genuinely easy here and this page won't inflate it: pagination, a
three-part body reassembled, JSON parsed out of JSON strings for the coordinates,
and dates built at UTC instead of parsed.

What we add is mostly what surrounds it — Amazon's rows in the same
[`Job`](/docs/objects/job) shape as every other [source](/docs/reference/sources)
rather than in Amazon's, dedup against the same role on [LinkedIn](/ats/linkedin),
expiry by board diffing since the feed declares none, and the adapter's upkeep
being ours instead of yours.

[Sources](/docs/reference/sources) · [Quickstart](/docs/quickstart)
