The resellflip API
You send the name and condition of an item. The API sends back a resale price, its range, and the number of completed sales found for that item. Two endpoints, prepaid credits, no subscription.
Your first call in two minutes
1. Create a key
Sign in (or create an account), open the developer space and click “Create a key”. Copy it right away: it is shown only once. Your first key comes with 1,000 free credits, i.e. 100 estimates, no card needed. The app is in French for now.
2. Paste this call into a terminal
Replace the key on the first line with yours. The rest works as is.
export RESELLFLIP_API_KEY="rf_live_paste_your_key_here"
curl https://resellflip.com/api/v1/estimate \
-H "Authorization: Bearer $RESELLFLIP_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Doudoune Uniqlo", "condition": "Bon", "size": "M"}'
3. Read the response
{
"price": 35,
"price_low": 28,
"price_high": 42,
"confidence": "moyenne",
"category": "Mode",
"comps_count": 0,
"sales_count": 0,
"rotation_days": null,
"rotation_samples": null,
"credits_remaining": 990
}
The values above are an example. Look at comps_count first: the number of
comparable items found in the corpus. sales_count says how many of them are
completed sales; at 0, no sale weighed on the price. Our corpus is young: today both are
often 0, and the price is then estimated without comparables. confidence is the
model’s view of the item, not of the corpus: test these two counters. The call cost you 10
credits; your balance is in credits_remaining.
Call the API from your server. In a browser or an app installed on your users’ devices, anyone could read the key.
Response fields
| Field | What it holds |
|---|---|
price |
The suggested resale price |
price_low, price_high |
The range. A fair price is an interval. |
confidence |
haute, moyenne or basse (high, medium, low).
The model’s view of the item, not of how many sales back it.
|
category |
The detected category |
comps_count |
The number of comparable items found: completed sales, or failing that, estimates of items still in stock. Can be 0. |
sales_count |
The completed sales found. At 0, no sale weighed on the price, even when
comps_count is positive.
|
rotation_days |
The median time from stocking to selling, in days. null until there are
five sales from three distinct sellers: we would rather say nothing than make up a
delay.
|
rotation_samples |
The number of sales behind that delay |
credits_remaining |
Your balance after the call |
For an item the corpus knows well, the response looks more like this: seven sales behind the price, and a resale delay.
{
"price": 50,
"price_low": 40,
"price_high": 60,
"confidence": "haute",
"category": "Mode",
"comps_count": 7,
"sales_count": 7,
"rotation_days": 21,
"rotation_samples": 7,
"credits_remaining": 90
}
The corpus is filtered before use: the last eighteen months, one row per seller, and never a figure built on a single seller.
Within version 1, we may add fields, never remove or rename them. Ignore the ones you do not know and your code will not break.
The two endpoints
Both take a POST, a JSON body, and your key in the
Authorization: Bearer header. No SDK, no webhooks, no sandbox: the trial runs
on the real corpus.
POST /api/v1/estimate · 10 credits
A full estimate. The JSON body:
| Field | Type | Required | Constraint |
|---|---|---|---|
name |
string | yes, unless images |
200 characters; the brand is inferred from it |
condition |
string | yes | one value from the list below |
size |
string | no | 30 characters |
notes |
string | no | 500 characters: flaws, details |
images |
array of objects | yes, unless name |
3 at most, format below |
gradingService |
string | no | PSA, BGS, CGC or SFG |
gradingGrade |
number | yes if gradingService |
1 to 10, in half points |
Text that is too long is truncated, not rejected. There is no brand field on
this endpoint.
condition only takes these values, written exactly as shown,
accents and capital included. They are the French values the app uses. Clothing and goods:
Neuf, Très bon, Bon or Satisfaisant.
Trading cards (Cardmarket scale): Mint, Near Mint,
Excellent, Good, Light Played, Played or
Poor. “Very good” or “neuf” return a 400, and nothing is charged.
images: up to 3 { "mime_type", "data" } objects. data is the image in
base64, without a data: prefix. Accepted types: image/jpeg,
image/png or image/webp. Each data is at most
2,800,000 characters, about 2 MB decoded. One invalid image and the whole call returns a
400, and nothing is charged.
{
"condition": "Bon",
"images": [
{ "mime_type": "image/jpeg", "data": "/9j/4AAQSkZJRgABAQ…" }
]
}
POST /api/v1/comps · 1 credit, 0 if the list is empty
The raw comparable items, without an estimate, five at most. Each row carries
kind: sale for a completed sale, estimate for an item
still in stock. For a sale, net_price is the net seller price:
what the seller received, platform fees deducted. For an estimate, it is the price its owner
is aiming for.
The body carries name, required (200 characters), and brand,
optional (80 characters). Without brand, the brand is inferred from the name.
No photos on this endpoint: to recognise an item from an image, use /estimate.
Add "sold_only": true to get sales only; it defaults to false.
comps_count and sales_count mean the same as on
/estimate, and can exceed five.
curl https://resellflip.com/api/v1/comps \
-H "Authorization: Bearer $RESELLFLIP_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Doudoune Uniqlo", "brand": "Uniqlo"}'
Example response:
{
"comps": [
{
"name": "Doudoune Uniqlo",
"brand": "Uniqlo",
"condition": "Bon",
"size": "M",
"net_price": 32.5,
"days_ago": 12,
"kind": "sale"
},
{
"name": "Doudoune ultra légère Uniqlo",
"brand": "Uniqlo",
"condition": "Très bon",
"size": "L",
"net_price": 40,
"days_ago": 5,
"kind": "estimate"
}
],
"comps_count": 9,
"sales_count": 9,
"rotation_days": 18,
"rotation_samples": 9,
"credits_remaining": 90
}
Today you will often get an empty list. It is a 200, and nothing is charged:
{
"comps": [],
"comps_count": 0,
"sales_count": 0,
"rotation_days": null,
"rotation_samples": null,
"credits_remaining": 1000
}
If the corpus takes more than 2.5 seconds to answer, you also get this empty list. So you cannot tell “no items” from a slow database. Either way, nothing is charged.
Errors
Every error carries a stable code and a readable error message.
Test the code: the message may change.
| Status | code |
Meaning | Charged? |
|---|---|---|---|
400 |
invalid_request |
Invalid body: missing field, condition not in the list, image rejected | No |
401 |
unauthorized |
Key missing, unknown or revoked | No |
402 |
insufficient_credits |
Balance too low for this call | No |
403 |
account_suspended |
API access suspended for this account: none of its keys work | No |
404 |
— | Endpoint not part of version 1 | No |
405 |
— | Method other than POST |
No |
429 |
rate_limited |
More than 60 calls per minute for this key | No |
500 |
internal_error |
Internal error | Refunded |
502 |
upstream_error |
The estimation service did not answer | Refunded |
503 |
unavailable |
Service unavailable | No |
504 |
upstream_error |
The estimate took too long. Try again. | Refunded |
A 429 rate_limited carries a Retry-After header, in
seconds. A 429 upstream_error, rarer, means our estimation service
is saturated: the call is refunded. The 401 returns the same message for a
missing key and an unknown one, on purpose. “Refunded” means the credits are taken at the
start of the call and given back straight away: your balance does not move.
Pricing
Prepaid credits, paid once, no subscription. An estimate costs 10 credits. A call to
/comps costs 1, and nothing when it finds nothing.
| Plan | Credits | Estimates | Price | Per estimate |
|---|---|---|---|---|
| Trial | 1,000 | 100 | Free | Once per account |
| Pack S | 10,000 | 1,000 | €49 | €0.049 |
| Pack M | 100,000 | 10,000 | €390 | €0.039 (−20%) |
| Pack L | 1,000,000 | 100,000 | €2,900 | €0.029 (−40%) |
| Beyond | — | — | On quote | — |
Credits do not expire in the current version of the offer. Unused credits from a pack are refundable on request. An error on our side (5xx) costs you nothing. Charged in euros. The publisher is exempt from VAT under article 293 B of the French tax code (CGI): the price shown is the price paid.
Beyond pack L, write to contact@resellflip.com. Send us your categories too: we will tell you what the corpus really covers for you.
Frequently asked questions
What happens when the corpus does not know the item?
You still get a price, but without any comparable item: comps_count and
sales_count are 0. The corpus is young, so this happens often. Read that field
before showing the price to your users.
Am I charged for a failed call?
No. An error on your side (400, 401, 402, 429) charges nothing. An error on ours (500, 502, 504) is refunded straight away. An outage (503) is not charged.
Do credits expire?
No, not in the current version of the offer. Unused credits from a purchased pack are refundable on request. Trial credits are not.
Can I store the comparable items returned?
You can show them to your users and keep them for as long as it takes to serve them. You cannot pile them up to rebuild the corpus, resell them as a database, query the API in a loop to harvest it, or use it to build a competing estimation service. The terms of use spell this out.
What if my key has leaked?
Revoke it and create a new one. We only keep its fingerprint, so we cannot send it back to you. Every call signed with it draws on your credits: never put it in code that runs on your users’ devices.
Terms
Use of the API is governed by the “API for professionals” section of the
terms of use: prepaid credits, acceptable use, key security, revocation
in case of abuse. The terms are written under French law, and only the French version is
binding. No seller’s personal data leaves through the API: a comparable item is an item
name, a brand, a condition, a size, a price, an age and its nature (kind): sale
or estimate.
Three uses are prohibited: using the API to offer a competing resale price estimation
service, harvesting or reselling the corpus (by querying /comps in a loop, for
example), and getting around the limits with several accounts or keys. If that happens,
every key on the account is suspended on the spot and answers
403 account_suspended. Credits used that way are not refunded. Unused credits
from a purchased pack stay refundable as usual, less the credits used in breach.
Already have an account? Sign in, then open the developer space.
Read next: How we calculate · App pricing