Skip to main content

Jobs API quickstart

Applies toJobs API

The Jobs API is the asynchronous REST surface, built for bulk and historical over-time extraction. You don't get data back in the response — instead you submit a job, poll until it finishes, then download the results as NDJSON files. This guide walks the full round-trip. Not sure this is the surface you want? See MCP or the API?.

Pick your region

The base URL depends on your contract region: https://api-us.edited.com/v1 or https://api-eu.edited.com/v1. The two regions serve the same API — the examples below use api-us; swap in api-eu if that's your region.

1. Get your access key​

Every request carries your EDITED access key in the x-api-key header — the same key across MCP, the Query API, and the Jobs API. If you don't have one yet, see Authentication & access.

2. Submit a job​

Submitting is a POST to /options/history/submit with the job description in the body:

curl -s -X POST "https://api-us.edited.com/v1/options/history/submit" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"start_date": "2025-08-10",
"end_date": "2025-08-30",
"granularity": "W",
"vertical": "apparel",
"currency": "USD",
"legacy_filters": { "in_stock": true }
}'

Every job needs these, and a hand-written body is easy to get subtly wrong — so check each one:

  • start_date / end_date — YYYY-MM-DD. end_date must be before today (a job ending today is rejected with "End date must be before today"); yesterday is fine.
  • granularity — a single letter: "D" daily, "W" weekly, or "M" monthly. Not the spelled-out word.
  • vertical — "apparel", "beauty", or "homeware", matching the data domain you're licensed for.
  • legacy_filters — how you scope the job. Its contents work exactly like the Query API's filters — see Filters. The Jobs API does not take a plain filters key (the most common submit-time mistake, since it's what an app export produces); scope goes under legacy_filters. As an alternative, filterset_id references a filter saved as a workbook in the EDITED app — handy when a business user owns the filter definition and your job just points at its stable ID.
  • currency — optional, and defaults to USD. It sets the currency of the main price fields; set it if you want those in a specific currency. You get each price in its original currency either way.

A successful submit returns a job ID — that's your handle for the next two steps.

3. Poll until it's done​

Check the job's status with a GET on /jobs/{jobID}:

curl -s "https://api-us.edited.com/v1/jobs/YOUR_JOB_ID" \
-H "x-api-key: YOUR_API_KEY"

The status moves through pending → processing → successful. Keep polling while it's non-terminal; stop if it reaches a terminal failure state (canceled, error, invalid_request) rather than retrying the poll.

Two things worth building in from the start:

  • Scale your poll interval to the job. Every ~30 seconds is a fine default for a small job; for a large backfill that will run for hours, poll far less often — tighter polling doesn't return results any sooner.
  • Keep the job alive. A job that isn't checked for 2 hours is auto-cancelled for inactivity. If that happens, you don't lose progress — resume continues from where it left off. Note that listing jobs doesn't count as a check; poll the job by its ID. See Rate limits → Jobs API for the full limits and result retention.

4. Download the results as they're ready​

You don't have to wait for the whole job to finish. Result files become available page by page while the job is still running, and pulling them as they appear — rather than all at once after the job completes — is the best way to avoid the rate limit most people hit (see the tip below). List the output files with a GET on /jobs/{jobID}/result-files:

curl -s "https://api-us.edited.com/v1/jobs/YOUR_JOB_ID/result-files" \
-H "x-api-key: YOUR_API_KEY"

This is a GET (some older documentation shows a POST — the spec is correct). The response gives you:

  • urls — the file locations to download for this page of results. Each time period's results may be split across multiple files of up to 10,000 documents each. Fetch a file with a GET on /jobs/{jobID}/results/{filename}.
  • next — a pagination token. To get the next page, send this token back in your next request — don't resend the same request unchanged, or you'll get the same page back every time.
  • results_available — false means this page isn't ready yet. Wait, then retry with the same token you already have; it's not an error and not a reason to start over.

Each file is newline-delimited JSON (NDJSON) — one option document per line, with the same fields documented in the data dictionary.

Pace your downloads

A large job can produce many files, and requesting all of them back-to-back the moment a job completes is a known way to hit a rate limit. Download files as each page becomes available rather than all at once, and treat a 429 as a signal to slow down, not a hard failure. See Rate limits.

5. Where to go next​

If you want to…Go to
Scope a job precisely — ranges, excludes, slugsFilters
Understand job limits, polling, and retentionRate limits & fair use
Handle errors and know what to retryErrors
Understand every field in a result recordData dictionary
See every endpoint — submit, manage, resume, resultsAPI reference
Pull data synchronously instead of in bulkQuery API quickstart
Check coverage before a big backfill

Before backfilling a long history for a new retailer, it's worth confirming EDITED actually has data across that window — otherwise you spend job time on empty periods. MCP's get_retailer_coverage tool answers this, and you can use it from a REST workflow: the identifiers are shared across surfaces. See Filters → Resolving values for more on mixing the surfaces.


Still stuck on your first job? Contact support@edited.com.