Poshmark sold listings
GET /v1/poshmark/sold searches one page of Poshmark US sold listings by keyword, with condition and price filters, and returns JSON.
https://api.soldgraph.com/v1/poshmark/soldSearch Poshmark US sold listings by keyword. Each call returns one page of results, not a full sales history. Poshmark has no public API of its own. See Poshmark API.
displayed_price is the listing's asking price, not what the buyer paid. Offers and bundles can change the final price. price, shipping, sold_at and took_offer are always null. displayed_shipping and shipping_text are always null too, because Poshmark search doesn't show shipping.
sold_date_text is when the listing changed to sold out, as a full timestamp. sold_date is its date part, like 2026-09-28. condition is Poshmark's own code, like nwt or ug. brand and size are what the seller entered.
| Parameter | Type | Default | Description |
|---|---|---|---|
q | string | Required | Search keywords, 1–200 characters, as you'd type them into the marketplace's search box. Be specific: model, size, grade, edition. |
page | integer, 1–100 | 1 | Source page to fetch. On Poshmark, Mercari and Depop, pages after 1 also need cursor. |
min_price | integer, 0–1000000 | Lowest price, in whole US dollars. Optional. Must not be more than max_price. You can send it without max_price. | |
max_price | integer, 0–1000000 | Highest price, in whole US dollars. Optional. You can send it without min_price. | |
marketplace | poshmark | poshmark | Optional. If sent, it must be poshmark. |
country | us | us | Only us is supported. |
condition | nwt, uln, ug or uf | One of Poshmark's own condition codes: nwt (new with tags), uln (like new), ug (good) or uf (fair). Rows use the same codes. Poshmark filters one condition at a time, so more than one returns 422. | |
cursor | string | The previous page's next_cursor. Leave it out on page 1. Required on every later page. |
curl -G https://api.soldgraph.com/v1/poshmark/sold \ -H "Authorization: Bearer $SOLDGRAPH_KEY" \ --data-urlencode "q=Levis 501" \ -d page=1The first call usually returns 202 and a job to poll. Search jobs covers polling and retries.
#Filters
conditiontakes one Poshmark code:nwt,uln,ugoruf. Poshmark filters one condition at a time, so more than one returns422.min_priceandmax_priceare whole US dollars. You can send either one alone.
Poshmark applies the filters, so reported_total counts only matching listings. Keep the same filters on every page.
#Condition codes
The API returns Poshmark's condition code as-is. It doesn't turn codes into words or match them to eBay's conditions. For reference, the codes mean:
| Code | Meaning | Can filter by it |
|---|---|---|
nwt | New with tags | Yes |
not_nwt | New without tags | No |
ret | Boutique or retail | No |
uln | Like new | Yes |
ug | Good | Yes |
uf | Fair | Yes |
#Pages and cursors
Start with page=1 and no cursor. For the next page, send the same q with page set to next_page and cursor set to next_cursor from the last result.
- A later page without a cursor, or a cursor in the wrong format, returns
422. - A cursor Poshmark doesn't accept fails the job with
error.coderejected. It costs nothing. page_sizecounts the rows Poshmark returned before we removed listings that aren't sold. Socountcan be smaller.- Results are in Poshmark's order, and
reported_totalmay be capped. - If Poshmark finds no matches, we drop the unrelated suggestions it shows and return an empty page.
In the Try it panel below, set page and paste next_cursor into cursor to get a later page. The dashboard Playground has a Next page button that does this for you.
#Example response
{ "request_id": "00000000-0000-4000-8000-000000000001", "status": "complete", "credits": 1, "cached": false, "result": { "provider": "poshmark", "country": "us", "query": "Levis 501", "page": 1, "page_size": 48, "count": 1, "reported_total": 1, "next_page": null, "collected_at": "2026-09-23T14:02:11Z", "schema_version": 1, "completeness": "provider_page_only", "data": [ { "id": "000000000000000000000001", "title": "Example Levi’s 501 jeans", "link": "https://poshmark.com/listing/000000000000000000000001", "displayed_price": { "amount": 35, "currency": "USD" }, "displayed_price_text": "$35.00", "displayed_shipping": null, "shipping_text": null, "sold_date": "2026-09-28", "sold_date_text": "2026-09-28T22:16:54-07:00", "condition": "ug", "seller_text": "closetofkate", "brand": "Levi's", "size": "32", "image": "https://di2ponv0v5otw.cloudfront.net/posts/example.jpg", "price": null, "shipping": null, "sold_at": null, "took_offer": null } ], "field_notes": "Displayed prices are listing asks, not verified transaction or accepted-offer amounts. sold_date_text is the inventory sold_out status change time; unverified fields are null. Only listings with sold_out inventory are included.", "next_cursor": null }}| Field | Type | Description |
|---|---|---|
request_id | string | ID of this request. Poll it at /v1/jobs/{request_id}. |
status | string | pending, complete or failed. Always check it, even on HTTP 200. |
credits | integer | Requests charged: 1 when complete, 0 while pending or when failed. |
cached | boolean | 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. |
error.code | string | Only when failed. See failed job codes. |
result | object | Only when complete. One source page from the marketplace. |
result.provider | string | Marketplace ID, like ebay or poshmark. |
result.country | string | Always us. |
result.query | string | The q you sent, with extra spaces removed. |
result.page | integer | The page you asked for. |
result.count | integer | Rows in result.data on this page. |
result.reported_total | integer | Total matches the marketplace reports for the search. It may be rounded or capped. |
result.next_page | integer | null | Send this as page to get the next page. Null on the last page. |
result.collected_at | string | When we collected the page, as an ISO 8601 timestamp. |
result.schema_version | integer | Version of this response shape. Currently 1. |
result.completeness | string | Always provider_page_only: one page, not a full sales history. |
result.field_notes | string | Plain-text notes on how to read this page's fields. |
result.page_size | integer | Rows Poshmark returned before we removed listings that aren't sold. It can be larger than count. |
result.next_cursor | string | null | Send this as cursor, with page=next_page, to get the next page. Null on the last page. |
result.data[].id | string | The marketplace's listing ID. |
result.data[].title | string | null | Listing title as shown. |
result.data[].link | string | URL of the listing on the marketplace. |
result.data[].displayed_price | object | { amount, currency } of the listing's asking price. Not what the buyer paid. |
result.data[].displayed_price_text | string | null | The price text as shown, like $189.00. |
result.data[].displayed_shipping | null | Always null on Poshmark. |
result.data[].shipping_text | null | Always null on Poshmark. |
result.data[].sold_date | string | Date part of sold_date_text, as YYYY-MM-DD. |
result.data[].sold_date_text | string | When the listing's inventory changed to sold out, as an ISO 8601 timestamp. Not a verified sale time. |
result.data[].condition | string | null | Poshmark's own condition code, as Poshmark returns it, like nwt or ug. See condition codes. |
result.data[].seller_text | string | null | The seller's Poshmark username. |
result.data[].brand | string | null | Brand as the seller entered it. |
result.data[].size | string | null | Size as the seller entered it. |
result.data[].image | string | null | Image URL on Poshmark's image CDN. |
result.data[].price | null | Always null. Reserved for a verified sale price. |
result.data[].shipping | null | Always null. Reserved for a verified shipping amount. |
result.data[].sold_at | null | Always null. Reserved for a verified sale time. |
result.data[].took_offer | null | Always null. Reserved for whether a Best Offer was accepted. |
The nwt filter can also return legacy ret (Boutique) rows. We observed this in live sold search; Poshmark announced conversion of Boutique listings to NWT. Returned condition codes are preserved rather than rewritten.