---
title: "OfferUp local listings"
method: GET
path: "/offerup/listings"
tags: ["OfferUp"]
---

# OfferUp local listings

`GET /offerup/listings`

## Request

- Base URL: `https://api.soldgraph.com/v1`
- URL: `https://api.soldgraph.com/v1/offerup/listings`
- Auth: HTTP bearer

Search one page of OfferUp US active listings near a ZIP code or point, about 50 rows. Prices are seller asks. No sold search. Results are cached for 15 minutes; a cache miss returns 202 and a job to poll.

## Query parameters

- `q` string, required
- `page` integer
- `min_price` integer
- `max_price` integer
- `marketplace` 'offerup'
- `country` 'us'
- `zip` string
- `lat` number
- `lon` number
- `radius` 5 | 10 | 20 | 25 | 30 | 50 | 80 | 100 | 200 | 5000
- `category` string
- `condition` string[]
- `sort` 'best_match' | 'newest' | 'nearest' | 'price_asc' | 'price_desc' | 'newest_model' | 'lowest_mileage'
- `vehicle_make` string[]
- `vehicle_max_mileage` 0 | 25000 | 50000 | 75000 | 100000 | 125000 | 150000 | 175000 | 200000
- `vehicle_style` string[]
- `vehicle_transmission` 'automatic' | 'manual'
- `vehicle_drivetrain` string[]
- `cursor` string

## Headers

- `Idempotency-Key` string

## Response `200`

Complete, including cache hits. Costs 1 request.

- OfferupListingsJob
  - `request_id` string, required: ID of this request. Poll it at /v1/jobs/{request_id}.
  - `status` 'pending' | 'complete' | 'failed', required: pending, complete or failed. Always check it, even on HTTP 200.
  - `credits` integer, required: Requests charged: 1 when complete, 0 for a page past the last one, while pending, or when failed.
  - `cached` boolean, required: True when the result came from the 15-minute cache.
  - `poll_url` string: Only while pending. A path like /v1/jobs/{id}: join it to https://api.soldgraph.com, not to the /v1 base URL.
  - `result` OfferupListingsPage
    - `provider` string, required: Marketplace ID, like ebay or poshmark.
    - `country` string, required: The country searched: us, or on eBay the country you sent.
    - `query` string, required: The q you sent, with extra spaces removed.
    - `page` integer, required: The page you asked for.
    - `count` integer, required: Rows returned: the page minus listings already returned on earlier pages of this search.
    - `reported_total` unknown, required
    - `next_page` integer, nullable, required: Send this as page to get the next page. Null on the last page, and on page 100, the deepest page served.
    - `collected_at` string, required: When we collected the page, as an ISO 8601 timestamp.
    - `schema_version` integer, required: Version of the result's shape for that marketplace: 1 or 2. It only rises when a field changes meaning.
    - `completeness` string, required: provider_page_only: one page as the marketplace served it, not a full history. TCGplayer recent sales say recent_sample_only.
    - `field_notes` string, required: Plain-text notes on how to read this page's fields.
    - `location` object, required: The search center as zip, latitude and longitude. Also radius_miles (applied), requested_radius_miles, and widened_radius_miles: the wider area OfferUp used for this page because nearby results ran out, else null.
    - `vehicle_search` boolean, required: True when OfferUp treated the search as cars and trucks. Vehicle radius options, filters and sorts apply only then.
    - `category_id` string, nullable, required: Category OfferUp applied, including one it picked from the keywords, such as 5.1 for "honda civic".
    - `page_size` integer, required: Listing rows on the source page, including repeats from earlier pages.
    - `summary` object, required: Price maths over the rows on this page: priced_count, currency, median, low, high. No row is removed from data. Rows with no single readable price are left out of the maths.
      - `priced_count` integer, required: Rows on this page that show one price.
      - `currency` string, required: Currency of the amounts below.
      - `median` number, nullable, required: Middle displayed price of those rows.
      - `low` number, nullable, required: Lowest displayed price.
      - `high` number, nullable, required: Highest displayed price.
      - `p25` number, nullable, required: First-quartile displayed price: a quarter of priced rows are at or below it.
      - `p75` number, nullable, required: Third-quartile displayed price. With `p25`, a range that ignores a stray accessory or parts listing.
    - `next_cursor` string, nullable, required: Send as cursor with page=next_page. Null at the end, when a page is mostly repeats, or after about 220 listings.
    - `data` OfferupListingsRow[], required
      - `id` string, required: OfferUp listing ID. Pass it to /v1/offerup/item for full details.
      - `title` string, required: Seller title, up to 2,000 characters.
      - `link` string, required: Public OfferUp listing URL.
      - `displayed_price` Money, required
        - `amount` number, required
        - `currency` string, required: ISO 4217 code, like USD.
      - `displayed_price_text` string, nullable, required: Formatted USD asking price.
      - `call_for_price` boolean, required: The listing shows "call for price", mostly dealer vehicles.
      - `firm_price` boolean, nullable, required: The seller marked the price firm, when the source says.
      - `condition` string, nullable, required: Condition label when search shows one. Usually null; the item endpoint always has condition.
      - `location_text` string, nullable, required: Seller-chosen area, such as Oakland, CA. Not an address.
      - `city` string, nullable, required: City from location_text when it reads "City, ST".
      - `state` string, nullable, required: Two-letter state from location_text.
      - `image` string, nullable, required: Thumbnail URL on the OfferUp image CDN.
      - `vehicle_miles` integer, nullable, required: Odometer reading shown on vehicle listings.
      - `promoted` boolean, required: A paid placement OfferUp mixed into the results.
      - `flags` string[], required: Raw source flags, such as LOCAL_PICKUP or CALL_FOR_PRICE.
  - `error` object
    - `code` 'page_mismatch' | 'schema' | 'network' | 'upstream' | 'throttled' | 'blocked' | 'rejected' | 'not_found' | 'filter_not_supported' | 'filter_not_applied' | 'location_not_served' | 'auth' | 'daily_limit' | 'deadline_exceeded' | 'credential_storage', required: Failed job code.
    - `message` string: What the code means, in plain words.

## Other responses

- `202`: Pending. Poll `poll_url` (or `Location`) with the same API key. Both are paths: join them to https://api.soldgraph.com.
- `401`: invalid_api_key: The API key is missing, malformed or revoked.
- `403`: account_suspended: The account is suspended, so none of its keys work. Email support to restore it. origin_not_allowed: A browser sent the request from a site that isn't allowed. Call the API from your server.
- `404`: not_found: No such path. request_not_found: The job ID is well-formed but unknown, or belongs to another account. An ID that isn't a UUID is no such path: 404 not_found. batch_not_found: No batch with that ID belongs to this account. Or a replay of a search that failed because of the search (the body is then the failed job): not_found.
- `405`: method_not_allowed: Wrong method for this route. Searches, jobs and usage use GET. Only /v1/batches takes POST.
- `409`: idempotency_conflict: This Idempotency-Key was already used with different search parameters. result_not_ready: CSV was requested before every search settled. Poll as JSON until status is complete, then ask for CSV.
- `413`: payload_too_large: The batch body is over 256 KB.
- `414`: uri_too_long: The query string is longer than 2,048 characters.
- `415`: unsupported_media_type: A batch must be sent as Content-Type: application/json.
- `422`: unsupported_or_invalid_query: An unknown parameter, or a value outside the documented range. error.param names the input to fix when it is one of the route's inputs. duplicate_parameter: A parameter was sent more than once. sort_not_implemented: sort=best_deal is not available. invalid_idempotency_key: Idempotency-Key must be 1–128 printable ASCII characters, with no spaces. invalid_wait: wait must be a whole number from 0 to 20. invalid_body: The batch body is not JSON, or has no searches list. batch_too_large: The batch holds more searches than your plan allows at once. pages counts as one search per page. invalid_format: format must be json or csv, and include must be results. Or a replay of a search that failed because of the search (the body is then the failed job): rejected, filter_not_supported, filter_not_applied, location_not_served.
- `429`: rate_limited: More than 60 API calls this minute for your account. quota_exceeded: Your plan's allowance is used up, and you have no extra requests left. too_many_pending: Your account has too many searches still pending. Wait for results before sending more.
- `503`: Temporary failure, or a replay of a failed search (the body is then the failed job). upstream_daily_limit: The marketplace's daily limit was reached, so new searches are paused. Cached results still work. queue_full: The collection queue is full. collection_unavailable: We can't collect from this marketplace right now. storage_unavailable: Our database is briefly unavailable. origin_unavailable: The edge couldn't reach our API server. service_unconfigured: The API is misconfigured on our side. Contact support.

---

[API](https://skmtc.dev/soldgraph/apis/soldgraph-api.md) · [All operations](https://skmtc.dev/soldgraph/apis/soldgraph-api/llms.txt) · [OpenAPI document](https://skmtc.dev/soldgraph/apis/soldgraph-api/revisions/137f0810f983?raw)
