API reference
Listings
The Listings resource is the source of truth for every item a partner brand offers across Repurch-powered marketplaces. Use it to create, read, update, and delete inventory; to upload photos; and to bulk-import via XLSX.
Payout and commission
Every listing carries a channel (clearance or exchange) that determines the commission. Clearance listings are charged 15% commission plus 20% VAT on the commission. Exchange is free to sell — no commission is charged. The payout field on every listing response shows the resulting partner payout per single sale, after the partner's delivery contribution is subtracted.
Categorising listings
Every listing needs a category — the buyer-facing grouping shoppers browse and filter by. It must be one of the values returned by GET /v1/listings/options (the categories array); it is partner-supplied, never inferred, so your integration maps your own product types onto it. Choose the category that matches the primary piece. When a single order is a multi-piece bundle (e.g. a 3+2 set, or a corner plus an armchair), use Sofa Sets and list each piece in measurements. Anything that doesn't fit falls back to Other.
| Your product type | Repurch category |
|---|---|
| Corner / L-shaped / sectional / chaise | Corner Sofas |
| 3-seater (and large 2.5-seaters) | 3-Seater Sofas |
| 2-seater / loveseat / compact sofa | 2-Seater Sofas |
| Sofa bed / sleeper / convertible | Sofa Beds |
| Armchair / accent chair / single recliner | Armchairs |
| Footstool / pouffe / ottoman | Footstools |
| Multi-piece bundle sold as one order | Sofa Sets |
| Anything else | Other |
Don't confuse category with item_types: the latter (e.g. 3-Seater, Footstool) labels the individual pieces inside measurements, while category is the single grouping the whole listing appears under. Categories are a fixed list — sync them from /v1/listings/options at integration time rather than hard-coding, so new categories are picked up automatically.
List listings
Returns a paginated list of listings for the authenticated brand. Supports filtering by post status and channel.
/v1/listingsAuthorization: Bearer … · Scopes: readQuery parameters
page integer | Page number, 1-indexed. Default 1. |
per_page integer | Items per page. Maximum 100. Default 20. |
status string | Filter by status: active, draft, or any. Default active. |
channel string | Filter by channel: clearance or exchange. Omit for both. |
Example request
curl "https://api.repurch.com/v1/listings?per_page=10&channel=clearance" \
-H "Authorization: Bearer re_pk_..."Example response
{
"data": [
{
"id": 12345,
"title": "Brown leather 3-seater sofa",
"price": 599,
"currency": "GBP",
"status": "active",
"image_url": "https://cdn.repurch.com/uploads/2026/06/leather-3-seater.jpg",
"brand_id": "furniture-co",
"url": "https://sofalistic.co.uk/sofas/3-seater-sofas/brown-leather-3-seater-sofa/",
"created_at": "2026-06-04T09:14:22+00:00",
"view_count": 187,
"category": "3-Seater Sofas",
"channel": "clearance",
"payout": 463.32
}
],
"meta": {
"page": 1,
"per_page": 20,
"total": 73,
"total_pages": 4,
"brand_id": "furniture-co"
}
}Response fields
data array | Array of listing summary objects, newest first. |
data[].id integer | Listing identifier. |
data[].price number | Sale price in GBP. |
data[].status string | One of active, draft, or closed. |
data[].channel string | Either clearance or exchange. |
data[].payout number | Estimated partner payout per single sale after commission, VAT, and delivery contribution. |
meta.total integer | Total number of listings matching the filters. |
meta.total_pages integer | Total page count given per_page. |
Errors
| Status | Code | Message |
|---|---|---|
| 401 | missing_bearer_token | No Authorization: Bearer header provided. |
| 401 | invalid_token | Token is malformed, expired, or signed with the wrong key. |
| 403 | forbidden | Caller is not a partner admin. |
Retrieve a listing
Returns the full detail for a single listing, including description, gallery, attributes, condition, and seller info. Listings owned by another brand return 404.
/v1/listings/{id}Authorization: Bearer … · Scopes: readPath parameters
id integerrequired | Listing identifier. |
Example request
curl https://api.repurch.com/v1/listings/12345 \
-H "Authorization: Bearer re_pk_..."Example response
{
"id": 12345,
"title": "Brown leather 3-seater sofa",
"price": 599,
"currency": "GBP",
"status": "active",
"image_url": "https://cdn.repurch.com/uploads/2026/06/leather-3-seater.jpg",
"brand_id": "furniture-co",
"url": "https://sofalistic.co.uk/sofas/3-seater-sofas/brown-leather-3-seater-sofa/",
"created_at": "2026-06-04T09:14:22+00:00",
"updated_at": "2026-06-08T14:02:11+00:00",
"view_count": 187,
"category": "3-Seater Sofas",
"channel": "clearance",
"payout": 463.32,
"description": "Generous chocolate leather 3-seater in excellent condition. Removable cushions, no pet exposure.",
"regular_price": 699,
"sale_price": 599,
"rrp": 1299,
"brand": "DFS",
"colour": "Brown",
"fabric": "Leather",
"age_years": "3 years old",
"condition": "excellent",
"available_from": "2026-06-15",
"exposed_to": [
"None"
],
"faults": [
"None"
],
"sku": "FCO-LE-3S-0042",
"warehouse_location": "Bay 12-C",
"delivery_contribution_gbp": 60,
"images": [
"https://cdn.repurch.com/uploads/2026/06/leather-3-seater.jpg",
"https://cdn.repurch.com/uploads/2026/06/leather-3-seater-arm.jpg"
],
"seller": {
"id": 42,
"display_name": "Sam Patel"
}
}Response fields
id integer | Listing identifier. |
channel string | Either clearance or exchange. Determines the commission rate applied to payout. |
condition string | One of like-new, excellent, gently-used, fair. |
exposed_to array | Multi-select array of household exposures: Dogs, Cats, Smoke, or None. |
faults array | Multi-select array. One of Rips or tears, Fire Label, or None must be present. |
delivery_contribution_gbp integer | Partner's delivery contribution in whole pounds. Subtracted from payout. |
quantity integer | Sellable stock remaining. Clearance listings can exceed 1; Exchange is always 1. |
payout number | Estimated partner payout per single sale. |
images array | Ordered list of image URLs. Index 0 is the cover (featured) image, the rest the gallery. |
Errors
| Status | Code | Message |
|---|---|---|
| 401 | missing_bearer_token | No Authorization: Bearer header provided. |
| 401 | invalid_token | Token is malformed, expired, or signed with the wrong key. |
| 403 | forbidden | Caller is not a partner admin. |
| 404 | listing_not_found | Listing not found. |
Create a listing
Creates a new inventory item for the authenticated brand. Returns the full listing detail on success.
/v1/listingsAuthorization: Bearer … · Scopes: writeRequest body
title stringrequired | Display title of the listing. |
description string | Long-form description. Plain text or basic HTML. |
channel string | Either clearance or exchange. Default exchange. |
price_gbp numberrequired | Sale price in GBP. |
sale_price_gbp number | Promotional price if different from price_gbp. |
rrp_gbp number | Original retail price, shown as struck-through. |
delivery_contribution_gbp integer | Partner contribution to delivery in whole pounds. One of 0, 30, 60, or 129 (=free delivery). |
condition stringrequired | One of like-new, excellent, gently-used, fair. |
category stringrequired | Buyer-facing marketplace category (e.g. "3-Seater Sofas"). Must match a value from GET /listings/options → categories. Distinct from item_types, which label the individual pieces inside measurements. |
brand string | Manufacturer brand (e.g. DFS, IKEA). Free text — created on first use. |
colour string | Dominant colour. Best matched to GET /listings/options → colours. |
fabric string | Upholstery material. Best matched to GET /listings/options → fabrics. |
age_years string | Age band, e.g. "3 years old". See GET /listings/options → ages for the full list. |
available_from string | ISO date (YYYY-MM-DD) when the item becomes collectable. |
quantity integer | Sellable stock for this listing. Business (Clearance) retailers can hold more than one identical unit; defaults to 1. Stock decrements on each sale and the listing closes when it reaches 0. (Exchange listings are always single-unit.) |
measurements array | Array of item dimensions, one object per piece: { type, w_cm, d_cm, h_cm } — e.g. { "type": "3-Seater", "w_cm": 210, "d_cm": 95, "h_cm": 88 }. type values come from GET /listings/options → item_types. |
exposed_to array | Multi-select. Values: Dogs, Cats, Smoke, None. Drives the buyer-facing Pet Free / Smoke Free labels (None = both free). |
faults array | Multi-select. One of Rips or tears, Fire Label, or None must be present. |
images array | Array of image URLs. They are fetched and imported into the media library automatically — the first becomes the cover (featured) image, the rest the gallery. No pre-upload needed; alternatively use attachment_ids. |
attachment_ids array | Attachment ids from POST /listings/upload-photo. First id = cover (featured) image, the rest = gallery. Use instead of images when you've pre-uploaded. |
sku string | Partner-side stock keeping unit. |
warehouse_location string | Free-form bay/aisle locator. |
Example request
curl https://api.repurch.com/v1/listings \
-H "Authorization: Bearer re_pk_..." \
-H "Content-Type: application/json" \
-d '{
"title": "Grey velvet corner sofa",
"description": "Excellent condition, no pet exposure.",
"channel": "clearance",
"price_gbp": 899.00,
"rrp_gbp": 1899.00,
"condition": "like-new",
"category": "Corner Sofas",
"brand": "DFS",
"colour": "Grey",
"fabric": "Velvet",
"age_years": "1 year old",
"quantity": 4,
"delivery_contribution_gbp": 60,
"exposed_to": ["None"],
"measurements": [
{ "type": "Corner Sofa", "w_cm": 265, "d_cm": 185, "h_cm": 88 }
],
"images": [
"https://cdn.example.com/sofas/grey-corner-1.jpg",
"https://cdn.example.com/sofas/grey-corner-2.jpg"
],
"sku": "FCO-VE-CN-0011"
}'Example response
{
"id": 12346,
"title": "Grey velvet corner sofa",
"price": 899,
"currency": "GBP",
"status": "active",
"channel": "clearance",
"payout": 695.16,
"category": "Corner Sofas",
"condition": "like-new",
"quantity": 4,
"images": [
"https://cdn.repurch.com/uploads/2026/06/grey-corner-1.jpg",
"https://cdn.repurch.com/uploads/2026/06/grey-corner-2.jpg"
]
}Errors
| Status | Code | Message |
|---|---|---|
| 401 | missing_bearer_token | No Authorization: Bearer header provided. |
| 401 | invalid_token | Token is malformed, expired, or signed with the wrong key. |
| 403 | forbidden | Caller is not a partner admin. |
| 400 | validation_failed | Listing could not be created: <field-level reasons>. |
Update a listing
Partial update. Any field accepted on create may be sent; omitted fields are left unchanged. Returns the updated listing detail.
/v1/listings/{id}Authorization: Bearer … · Scopes: writePath parameters
id integerrequired | Listing identifier. |
Request body
any field from POST /v1/listings varies | Send only the fields you want to change. At least one field is required. |
Example request
curl -X PATCH https://api.repurch.com/v1/listings/12345 \
-H "Authorization: Bearer re_pk_..." \
-H "Content-Type: application/json" \
-d '{ "price_gbp": 549.00 }'Example response
{
"id": 12345,
"title": "Brown leather 3-seater sofa",
"price": 549,
"status": "active",
"channel": "clearance",
"payout": 424.32
}Errors
| Status | Code | Message |
|---|---|---|
| 401 | missing_bearer_token | No Authorization: Bearer header provided. |
| 401 | invalid_token | Token is malformed, expired, or signed with the wrong key. |
| 403 | forbidden | Caller is not a partner admin. |
| 400 | no_fields | PATCH body must include at least one field to update. |
| 403 | forbidden_not_owner | You can only modify listings you created. |
| 404 | listing_not_found | Listing not found. |
| 400 | validation_failed | Update rejected: <field-level reasons>. |
Delete a listing
Soft-deletes a listing. The item is moved to the trash and removed from the consumer marketplace, but historical orders that reference it stay intact for remittance.
/v1/listings/{id}Authorization: Bearer … · Scopes: writePath parameters
id integerrequired | Listing identifier. |
Example request
curl -X DELETE https://api.repurch.com/v1/listings/12345 \
-H "Authorization: Bearer re_pk_..."Example response
{
"deleted": true,
"id": 12345
}Errors
| Status | Code | Message |
|---|---|---|
| 401 | missing_bearer_token | No Authorization: Bearer header provided. |
| 401 | invalid_token | Token is malformed, expired, or signed with the wrong key. |
| 403 | forbidden | Caller is not a partner admin. |
| 403 | forbidden_not_owner | You can only delete listings you created. |
| 404 | listing_not_found | Listing not found. |
List taxonomy options
Returns the canonical option lists used by the create-listing form: brands, colours, fabrics, age bands, categories, item types, conditions, exposures, and faults.
/v1/listings/optionsAuthorization: Bearer … · Scopes: readExample request
curl https://api.repurch.com/v1/listings/options \
-H "Authorization: Bearer re_pk_..."Example response
{
"brands": [
"DFS",
"IKEA",
"Loaf",
"Sofa.com",
"Habitat",
"John Lewis",
"Made.com",
"Next",
"SCS",
"Sofology",
"Other"
],
"colours": [
"Beige",
"Black",
"Blue",
"Brown",
"Charcoal",
"Cream",
"Green",
"Grey",
"Ivory",
"Mink",
"Natural",
"Navy",
"Pink",
"Red",
"Silver",
"Stone",
"Tan",
"Teal",
"White",
"Yellow"
],
"fabrics": [
"Velvet",
"Leather",
"Faux Leather",
"Linen",
"Cotton",
"Chenille",
"Bouclé",
"Wool",
"Polyester",
"Microfiber",
"Suede",
"Faux Suede",
"Silk",
"Tweed",
"Corduroy",
"Canvas",
"Jacquard",
"Acrylic",
"Nylon",
"Viscose",
"Rattan",
"Wicker",
"Mixed Fabric",
"Other"
],
"ages": [
"Less than 1 year",
"1 year old",
"2 years old",
"3 years old",
"4 years old",
"5 years old",
"6 years old",
"7 years old",
"8 years old",
"9 years old",
"10 years old",
"11 years old",
"12 years old",
"13 years old",
"14 years old",
"15+ years old"
],
"categories": [
"Corner Sofas",
"3-Seater Sofas",
"2-Seater Sofas",
"Sofa Beds",
"Armchairs",
"Footstools",
"Sofa Sets",
"Other"
],
"item_types": [
"Corner Sofa",
"4-Seater",
"3-Seater",
"2-Seater",
"Chair",
"Sofa Bed",
"Sofa Set",
"U-Shape Sofa",
"Footstool"
],
"conditions": [
{
"value": "like-new",
"label": "Like new",
"help": "Near-perfect condition with virtually no signs of use."
},
{
"value": "excellent",
"label": "Excellent",
"help": "No stains or defects, may show very light signs of minimal use."
},
{
"value": "gently-used",
"label": "Gently used",
"help": "Clean, minor marks and stains that don't affect function or appearance."
},
{
"value": "fair",
"label": "Fair",
"help": "Functional, noticeable wear or marks."
}
],
"exposures": [
{
"value": "Dogs",
"label": "Dogs"
},
{
"value": "Cats",
"label": "Cats"
},
{
"value": "Smoke",
"label": "Smoke"
},
{
"value": "None",
"label": "None of the above"
}
],
"faults": [
{
"value": "Rips or tears",
"label": "Rips or tears"
},
{
"value": "Fire Label",
"label": "Has fire safety label"
},
{
"value": "None",
"label": "None of the above"
}
]
}Response fields
brands / colours / fabrics / ages / categories / item_types array of strings | Use these values verbatim when submitting create-listing payloads. |
conditions / exposures / faults array of objects | Each entry has a value to submit and a label to render. conditions entries also carry a help string for the form. |
Errors
| Status | Code | Message |
|---|---|---|
| 401 | missing_bearer_token | No Authorization: Bearer header provided. |
| 401 | invalid_token | Token is malformed, expired, or signed with the wrong key. |
| 403 | forbidden | Caller is not a partner admin. |
Upload a photo
Stores a base64-encoded image in the media library and returns its public URL plus thumbnail variants. Pass the URL (or attachment_id) back in the listing create or update payload.
/v1/listings/upload-photoAuthorization: Bearer … · Scopes: writeRequest body
image_base64 stringrequired | Base64-encoded image bytes. JPEG, PNG, WebP, or GIF. Maximum 10 MB decoded. |
filename string | Optional filename for the stored asset. Defaults to upload.jpg. |
Example request
curl https://api.repurch.com/v1/listings/upload-photo \
-H "Authorization: Bearer re_pk_..." \
-H "Content-Type: application/json" \
-d '{
"image_base64": "/9j/4AAQSkZJRgABAQ...",
"filename": "leather-3-seater.jpg"
}'Example response
{
"attachment_id": 98765,
"url": "https://cdn.repurch.com/uploads/2026/06/leather-3-seater.jpg",
"sizes": {
"medium": "https://cdn.repurch.com/uploads/2026/06/leather-3-seater-300x300.jpg",
"large": "https://cdn.repurch.com/uploads/2026/06/leather-3-seater-1024x1024.jpg"
},
"mime": "image/jpeg"
}Response fields
attachment_id integer | Internal attachment id. Pass via attachment_ids on listing create or update. |
url string | Public CDN URL for the original upload. |
sizes.medium / sizes.large string | Pre-generated thumbnail URLs. May be empty if generation is still pending. |
mime string | Detected MIME type. |
Errors
| Status | Code | Message |
|---|---|---|
| 401 | missing_bearer_token | No Authorization: Bearer header provided. |
| 401 | invalid_token | Token is malformed, expired, or signed with the wrong key. |
| 403 | forbidden | Caller is not a partner admin. |
| 400 | no_image | image_base64 is required. |
| 400 | bad_image_base64 | image_base64 is not valid base64. |
| 413 | image_too_large | Image must be smaller than 10MB. |
| 415 | unsupported_mime | Unsupported image type. Allowed: jpeg, png, webp, gif. |
Download the bulk import template
Returns an XLSX file pre-populated with the partner's taxonomy as native Excel dropdowns. Use it as the starting point for any bulk upload — the column order and validation rules match what POST /listings/bulk-validate expects.
/v1/listings/bulk-templateAuthorization: Bearer … · Scopes: readExample request
curl https://api.repurch.com/v1/listings/bulk-template \
-H "Authorization: Bearer re_pk_..." \
-o repurch-clearance-import-template.xlsxExample response
{
"content_type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"content_disposition": "attachment; filename=\"repurch-clearance-import-template.xlsx\""
}Response fields
(binary body) bytes | Raw XLSX bytes. Save to disk; do not attempt to parse as JSON. |
Errors
| Status | Code | Message |
|---|---|---|
| 401 | missing_bearer_token | No Authorization: Bearer header provided. |
| 401 | invalid_token | Token is malformed, expired, or signed with the wrong key. |
| 403 | forbidden | Caller is not a partner admin. |
Validate a bulk file
Dry-run a CSV or XLSX upload. Parses every row, applies the same validation as create-listing, and returns a per-row verdict. Nothing is written.
/v1/listings/bulk-validateAuthorization: Bearer … · Scopes: writeRequest body
file_b64 string | Base64-encoded XLSX or CSV bytes. Preferred path. |
csv_text string | Raw CSV text. Legacy path; prefer file_b64. |
Example request
curl https://api.repurch.com/v1/listings/bulk-validate \
-H "Authorization: Bearer re_pk_..." \
-H "Content-Type: application/json" \
-d '{ "file_b64": "UEsDBBQAAAAIA..." }'Example response
{
"row_count": 42,
"error_count": 2,
"max_rows": 200,
"headers": [
"title",
"price_gbp",
"category",
"condition",
"brand",
"colour",
"fabric",
"age_years"
],
"rows": [
{
"row": 2,
"title": "Grey velvet corner sofa",
"status": "ok",
"errors": []
},
{
"row": 3,
"title": "Tan armchair",
"status": "error",
"errors": [
"price_gbp_required",
"category_required"
]
}
]
}Response fields
row_count integer | Total rows parsed from the file (excluding the header row). |
error_count integer | Number of rows that failed validation. |
max_rows integer | Cap on rows per file. Currently 200 — split larger imports into multiple calls. Background-job processing for unbounded uploads lands in a future release. |
headers array | Column headers as they appeared in the uploaded file. |
rows[].row integer | 1-indexed CSV/XLSX line number (header row is row 1, so first data row is row 2). |
rows[].title string | Listing title from the row, or '(missing title)' if blank. |
rows[].status string | Either 'ok' or 'error'. |
rows[].errors array | List of validation error codes for this row. Empty for 'ok' rows. |
Errors
| Status | Code | Message |
|---|---|---|
| 401 | missing_bearer_token | No Authorization: Bearer header provided. |
| 401 | invalid_token | Token is malformed, expired, or signed with the wrong key. |
| 403 | forbidden | Caller is not a partner admin. |
| 400 | bad_file | Upload payload is not valid base64, or no file supplied. |
Commit a bulk file
Re-parses the file and creates listings for every valid row. Auto-tags every listing with the caller's brand_id and sets channel to clearance. Returns per-row results.
/v1/listings/bulk-commitAuthorization: Bearer … · Scopes: writeRequest body
file_b64 string | Base64-encoded XLSX or CSV bytes. Preferred path. |
csv_text string | Raw CSV text. Legacy path. |
Example request
curl https://api.repurch.com/v1/listings/bulk-commit \
-H "Authorization: Bearer re_pk_..." \
-H "Content-Type: application/json" \
-d '{ "file_b64": "UEsDBBQAAAAIA..." }'Example response
{
"row_count": 42,
"success_count": 40,
"error_count": 2,
"rows": [
{
"row": 2,
"title": "Grey velvet corner sofa",
"status": "success",
"product_id": 12347,
"url": "https://sofalistic.co.uk/sofas/corner-sofas/grey-velvet-corner-sofa/"
},
{
"row": 3,
"title": "Tan armchair",
"status": "error",
"message": "price_gbp_required · category_required"
}
]
}Response fields
row_count integer | Total rows in the file. |
success_count integer | Rows that created a listing. |
error_count integer | Rows that failed. Valid rows are still committed — partial-success is normal. |
rows[].title string | Listing title from the row, or '(missing title)' if blank. |
rows[].status string | 'success' or 'error'. |
rows[].product_id integer | Present on success rows. ID of the newly created listing. |
rows[].url string | Present on success rows. Live URL of the listing on the marketplace. |
rows[].message string | Present on error rows. Pipe-separated validation error codes for that row. |
Errors
| Status | Code | Message |
|---|---|---|
| 401 | missing_bearer_token | No Authorization: Bearer header provided. |
| 401 | invalid_token | Token is malformed, expired, or signed with the wrong key. |
| 403 | forbidden | Caller is not a partner admin. |
| 400 | bad_file | Upload payload is not valid base64, or no file supplied. |
Bulk delete listings
Soft-deletes up to 100 listings in a single call. Brand-scope and ownership checks are applied per-id; partial failures are returned in the response.
/v1/listings/bulk-deleteAuthorization: Bearer … · Scopes: writeRequest body
ids arrayrequired | Array of listing ids. Maximum 100 per call. |
Example request
curl https://api.repurch.com/v1/listings/bulk-delete \
-H "Authorization: Bearer re_pk_..." \
-H "Content-Type: application/json" \
-d '{ "ids": [12345, 12346, 12347] }'Example response
{
"success_count": 3,
"error_count": 1,
"results": [
{
"id": 12345,
"ok": true
},
{
"id": 12346,
"ok": true
},
{
"id": 12347,
"ok": true
},
{
"id": 12348,
"ok": false,
"errors": [
"forbidden_not_owner"
]
}
]
}Response fields
success_count integer | Listings successfully deleted. |
error_count integer | Listings that could not be deleted. |
results array | Per-id outcome. |
Errors
| Status | Code | Message |
|---|---|---|
| 401 | missing_bearer_token | No Authorization: Bearer header provided. |
| 401 | invalid_token | Token is malformed, expired, or signed with the wrong key. |
| 403 | forbidden | Caller is not a partner admin. |
| 400 | no_ids | Provide at least one listing ID. |
| 400 | too_many | Bulk delete is capped at 100 listings per call. |