repurch/ docs
Dashboard ↗repurch.com ↗

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 typeRepurch category
Corner / L-shaped / sectional / chaiseCorner Sofas
3-seater (and large 2.5-seaters)3-Seater Sofas
2-seater / loveseat / compact sofa2-Seater Sofas
Sofa bed / sleeper / convertibleSofa Beds
Armchair / accent chair / single reclinerArmchairs
Footstool / pouffe / ottomanFootstools
Multi-piece bundle sold as one orderSofa Sets
Anything elseOther

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.

GET/v1/listings
Auth: Authorization: Bearer … · Scopes: read

Query 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
curl "https://api.repurch.com/v1/listings?per_page=10&channel=clearance" \
  -H "Authorization: Bearer re_pk_..."

Example response

json
{
  "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

StatusCodeMessage
401missing_bearer_tokenNo Authorization: Bearer header provided.
401invalid_tokenToken is malformed, expired, or signed with the wrong key.
403forbiddenCaller 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.

GET/v1/listings/{id}
Auth: Authorization: Bearer … · Scopes: read

Path parameters

id
integerrequired
Listing identifier.

Example request

curl
curl https://api.repurch.com/v1/listings/12345 \
  -H "Authorization: Bearer re_pk_..."

Example response

json
{
  "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

StatusCodeMessage
401missing_bearer_tokenNo Authorization: Bearer header provided.
401invalid_tokenToken is malformed, expired, or signed with the wrong key.
403forbiddenCaller is not a partner admin.
404listing_not_foundListing not found.

Create a listing

Creates a new inventory item for the authenticated brand. Returns the full listing detail on success.

POST/v1/listings
Auth: Authorization: Bearer … · Scopes: write

Request 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
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

json
{
  "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

StatusCodeMessage
401missing_bearer_tokenNo Authorization: Bearer header provided.
401invalid_tokenToken is malformed, expired, or signed with the wrong key.
403forbiddenCaller is not a partner admin.
400validation_failedListing 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.

PATCH/v1/listings/{id}
Auth: Authorization: Bearer … · Scopes: write

Path 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
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

json
{
  "id": 12345,
  "title": "Brown leather 3-seater sofa",
  "price": 549,
  "status": "active",
  "channel": "clearance",
  "payout": 424.32
}

Errors

StatusCodeMessage
401missing_bearer_tokenNo Authorization: Bearer header provided.
401invalid_tokenToken is malformed, expired, or signed with the wrong key.
403forbiddenCaller is not a partner admin.
400no_fieldsPATCH body must include at least one field to update.
403forbidden_not_ownerYou can only modify listings you created.
404listing_not_foundListing not found.
400validation_failedUpdate 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.

DELETE/v1/listings/{id}
Auth: Authorization: Bearer … · Scopes: write

Path parameters

id
integerrequired
Listing identifier.

Example request

curl
curl -X DELETE https://api.repurch.com/v1/listings/12345 \
  -H "Authorization: Bearer re_pk_..."

Example response

json
{
  "deleted": true,
  "id": 12345
}

Errors

StatusCodeMessage
401missing_bearer_tokenNo Authorization: Bearer header provided.
401invalid_tokenToken is malformed, expired, or signed with the wrong key.
403forbiddenCaller is not a partner admin.
403forbidden_not_ownerYou can only delete listings you created.
404listing_not_foundListing 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.

GET/v1/listings/options
Auth: Authorization: Bearer … · Scopes: read

Example request

curl
curl https://api.repurch.com/v1/listings/options \
  -H "Authorization: Bearer re_pk_..."

Example response

json
{
  "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

StatusCodeMessage
401missing_bearer_tokenNo Authorization: Bearer header provided.
401invalid_tokenToken is malformed, expired, or signed with the wrong key.
403forbiddenCaller 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.

POST/v1/listings/upload-photo
Auth: Authorization: Bearer … · Scopes: write

Request 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
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

json
{
  "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

StatusCodeMessage
401missing_bearer_tokenNo Authorization: Bearer header provided.
401invalid_tokenToken is malformed, expired, or signed with the wrong key.
403forbiddenCaller is not a partner admin.
400no_imageimage_base64 is required.
400bad_image_base64image_base64 is not valid base64.
413image_too_largeImage must be smaller than 10MB.
415unsupported_mimeUnsupported 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 &mdash; the column order and validation rules match what POST /listings/bulk-validate expects.

GET/v1/listings/bulk-template
Auth: Authorization: Bearer … · Scopes: read

Example request

curl
curl https://api.repurch.com/v1/listings/bulk-template \
  -H "Authorization: Bearer re_pk_..." \
  -o repurch-clearance-import-template.xlsx

Example response

json
{
  "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

StatusCodeMessage
401missing_bearer_tokenNo Authorization: Bearer header provided.
401invalid_tokenToken is malformed, expired, or signed with the wrong key.
403forbiddenCaller 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.

POST/v1/listings/bulk-validate
Auth: Authorization: Bearer … · Scopes: write

Request 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
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

json
{
  "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

StatusCodeMessage
401missing_bearer_tokenNo Authorization: Bearer header provided.
401invalid_tokenToken is malformed, expired, or signed with the wrong key.
403forbiddenCaller is not a partner admin.
400bad_fileUpload 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.

POST/v1/listings/bulk-commit
Auth: Authorization: Bearer … · Scopes: write

Request body

file_b64
string
Base64-encoded XLSX or CSV bytes. Preferred path.
csv_text
string
Raw CSV text. Legacy path.

Example request

curl
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

json
{
  "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

StatusCodeMessage
401missing_bearer_tokenNo Authorization: Bearer header provided.
401invalid_tokenToken is malformed, expired, or signed with the wrong key.
403forbiddenCaller is not a partner admin.
400bad_fileUpload 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.

POST/v1/listings/bulk-delete
Auth: Authorization: Bearer … · Scopes: write

Request body

ids
arrayrequired
Array of listing ids. Maximum 100 per call.

Example request

curl
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

json
{
  "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

StatusCodeMessage
401missing_bearer_tokenNo Authorization: Bearer header provided.
401invalid_tokenToken is malformed, expired, or signed with the wrong key.
403forbiddenCaller is not a partner admin.
400no_idsProvide at least one listing ID.
400too_manyBulk delete is capped at 100 listings per call.