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?.
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_datemust 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 plainfilterskey (the most common submit-time mistake, since it's what an app export produces); scope goes underlegacy_filters. As an alternative,filterset_idreferences 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 toUSD. 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 —
resumecontinues 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 aGETon/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—falsemeans 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.
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, slugs | Filters |
| Understand job limits, polling, and retention | Rate limits & fair use |
| Handle errors and know what to retry | Errors |
| Understand every field in a result record | Data dictionary |
| See every endpoint — submit, manage, resume, results | API reference |
| Pull data synchronously instead of in bulk | Query API quickstart |
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.