Sellmate Sellmate

Developers

This API lets an AI agent read the ads it has to publish and report back what it did on each marketplace. It only gives access to the listings of the account that created the key.

Authentication

Create an API key from your profile page. It is shown only once. Send it as a bearer token, and ask for JSON:

Authorization: Bearer YOUR_API_KEY
Accept: application/json

All URLs below are relative to https://sellmate.bancel.org/api. Requests without a valid key get a 401.

Listings

A listing is the publication of one item on one marketplace. Marketplaces are identified by a slug: leboncoin, rakuten, ebay and vinted.

GET /listings

Lists your listings, oldest first, 50 per page. Use the page parameter to move through pages; the response also holds the standard Laravel links and meta pagination keys.

  • status (optional): only listings in this status, see the statuses below.
  • marketplace (optional): only listings on this marketplace slug.
curl "https://sellmate.bancel.org/api/listings?status=pending&marketplace=vinted" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"

GET /listings/{id}

Returns one listing. A listing that belongs to another account answers 403.

The listing object

Each listing comes with its item and the item's photos. Photo URLs are absolute and can be downloaded directly. Photos are ordered by position. Prices are decimal strings and dates are ISO 8601.

{
  "data": {
    "id": 12,
    "status": "pending",
    "marketplace": "vinted",
    "external_id": null,
    "url": null,
    "price": null,
    "meta": null,
    "error_message": null,
    "published_at": null,
    "ended_at": null,
    "last_checked_at": null,
    "created_at": "2026-10-31T09:12:44+00:00",
    "item": {
      "id": 3,
      "title": "Road bike",
      "description": "Lightly used, size 54.",
      "price": "250.00",
      "status": "active",
      "address": {
        "id": 2,
        "label": "Home",
        "street": "12 rue des Lilas",
        "complement": "Escalier B",
        "postal_code": "69003",
        "city": "Lyon",
        "country": "France",
        "full_address": "12 rue des Lilas, Escalier B, 69003 Lyon, France"
      },
      "photos": [
        { "id": 7, "url": "https://sellmate.bancel.org/storage/items/3/abc.jpg", "position": 1 }
      ]
    }
  }
}

The listing price is the price actually asked on the marketplace, when you record one. The item's price is the one entered in Sellmate.

The item's address is the place where the item can be picked up, chosen by the user on the item. Use it as the location of the ad. It is null when the user has not chosen one yet: do not guess an address, report the listing as failed with an error_message asking the user to choose one. full_address is the address on one line.

PATCH /listings/{id}

Reports what happened on the marketplace. Send only the fields you want to change; PUT works the same way. The updated listing is returned. Every update also refreshes last_checked_at, so you can use a call without changes to record that you checked the ad.

  • status: the new status. Only the transitions listed below are accepted.
  • external_id: the ad identifier on the marketplace, up to 255 characters. It must be unique per marketplace.
  • url: the public address of the ad, http or https.
  • price: the price asked on the marketplace, from 0 to 99999999.99 with at most two decimals.
  • error_message: why a publication failed. It is shown to the user.
  • meta: any JSON object you want to keep with the listing, for example a category or a draft identifier.

Send null to clear external_id, url, price, error_message or meta.

curl -X PATCH "https://sellmate.bancel.org/api/listings/12" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"status": "published", "external_id": "4481920", "url": "https://www.vinted.fr/items/4481920"}'

Statuses

  • pending: the user asked for publication. This is the agent's to-do list.
  • published: the ad is online. An external_id or a url is required.
  • failed: the agent could not publish. Set error_message.
  • to_remove: the ad is online but must be taken down, because the user asked for it or the item was sold. Remove the ad, then report it as ended (or sold).
  • sold: the item was sold through this ad. The item is marked as sold too, which closes its other listings.
  • ended: the ad is over, cancelled or removed.

Allowed transitions

From To
pending published, failed, ended
published sold, ended, to_remove
failed pending, ended
sold final
ended final
to_remove sold, ended

Sending the status a listing already has is accepted and does nothing.

Side effects

  • published_at is set when the listing becomes published, and ended_at when it becomes sold or ended.
  • Moving to published or back to pending clears error_message, unless you send one in the same request.
  • Every status change is recorded in the listing's history.

Errors

  • 401: missing or invalid API key.
  • 403: the listing belongs to another account.
  • 404: the listing does not exist.
  • 422: invalid input, for example a forbidden status transition, or a published listing with neither external_id nor url.
{
  "message": "A pending listing cannot become sold.",
  "errors": {
    "status": ["A pending listing cannot become sold."]
  }
}

MCP server

Agents that speak the Model Context Protocol can use Sellmate without calling the REST API themselves. The server is a remote MCP endpoint at https://sellmate.bancel.org/mcp. It uses the same API key as a bearer token and only gives access to your own listings. With Claude Code:

claude mcp add --transport http sellmate https://sellmate.bancel.org/mcp --header "Authorization: Bearer YOUR_API_KEY"

The command is on a single line so it works in any shell, including Windows PowerShell and Command Prompt.

Tools:

  • list-listings: same as GET /listings, with the optional status, marketplace and page arguments. It returns data plus page, last_page and total.
  • get-listing: same as GET /listings/{id}, with the id argument.
  • update-listing: same as PATCH /listings/{id}, with the id argument and the fields described above. The statuses, transitions and side effects are identical.

A listing that does not exist or belongs to another account answers with a "not found" error, and invalid input comes back as an error listing what is wrong, as the REST API's 422 does.

Typical agent loop

  1. Fetch GET /listings?status=pending, then publish each ad on its marketplace using the item's title, description, price and photos.
  2. On success, PATCH the listing to published with the ad's external_id and url. On failure, set failed and an error_message. A failed listing can be moved back to pending to be retried.
  3. Fetch GET /listings?status=to_remove, take those ads down and PATCH them to ended.
  4. Now and then, check the published ads. Report sold or ended when they changed, otherwise send an update without changes to refresh last_checked_at.