Overview
The API is read-only. Every request is a GET and every response is JSON.
All prices are outright purchase prices in Qatari riyals (QAR), whole numbers. Subscription and monthly prices are not part of this API.
Only products currently for sale on revio.me are returned. Pre-order items are not included. When a deal is running, the price you get is the deal price.
How prices vary
- By storage: each storage size has its own price (e.g. 256 GB and 512 GB). See
storages[].price. - By colour: a colour can occasionally cost more or less than its storage's base price.
variants[].pricealways has the exact price for each colour and storage combination, so use that when showing or charging a price.
Try it in Postman
Download the ready-made collection with every endpoint set up:
- In Postman, choose Import and select the downloaded file.
- Open the Revio Product API collection, go to Variables, and paste your key into
apiKey. - Save, then run any request. The key is sent automatically.
Authentication
Every request to /v1 needs your secret API key in the x-api-key header. Revio gives each partner their own key.
curl https://api.revio.me/v1/products \
-H "x-api-key: YOUR_API_KEY"
A missing or wrong key returns 401:
{ "error": "unauthorized" }
Endpoints
GET /v1/products
Every product for sale, as a short summary without the per-colour detail.
| Query parameter | Values | What it does |
|---|---|---|
category | phone, laptop, tablet, watch | Only that type of device |
brand | e.g. apple | Only that brand (not case-sensitive) |
inStock | true | Only products that can be bought right now |
curl "https://api.revio.me/v1/products?category=phone&inStock=true" \
-H "x-api-key: YOUR_API_KEY"
{
"currency": "QAR",
"count": 6,
"products": [
{
"id": "iphone-17-pro",
"url": "https://revio.me/product/iphone-17-pro",
"name": "iPhone 17 Pro",
"brand": "Apple",
"category": "phone",
"condition": "new",
"currency": "QAR",
"purchasable": true,
"onDeal": false,
"priceFrom": 4349,
"compareAtPriceFrom": null,
"image": "https://storage.googleapis.com/revioflex-media-2026/products/iphone-17-pro/…jpg",
"colors": ["Cosmic Orange", "Deep Blue", "Silver"],
"storages": ["256 GB", "512 GB"]
}
]
}
GET /v1/products/{id}
One product, with a price and stock status for every colour and storage combination. {id} is the product's id from the list, e.g. iphone-17.
curl https://api.revio.me/v1/products/iphone-17 \
-H "x-api-key: YOUR_API_KEY"
{
"id": "iphone-17",
"url": "https://revio.me/product/iphone-17",
"name": "iPhone 17",
"brand": "Apple",
"tagline": "",
"description": "",
"category": "phone",
"condition": "new",
"currency": "QAR",
"purchasable": true,
"onDeal": false,
"priceFrom": 3249,
"compareAtPriceFrom": null,
"images": [{ "url": "https://storage.googleapis.com/…/black-v3.webp", "alt": "iPhone 17" }],
"colors": [
{ "name": "Black", "hex": "#1F1F1F", "image": "https://storage.googleapis.com/…/black-v3.webp" },
{ "name": "Sage", "hex": "#B7C4B0", "image": "https://storage.googleapis.com/…/sage-v3.webp" }
],
"storages": [
{ "label": "256 GB", "price": 3249, "compareAtPrice": null, "onDeal": false, "inStock": true },
{ "label": "512 GB", "price": 3899, "compareAtPrice": null, "onDeal": false, "inStock": true }
],
"variants": [
{ "id": "256 GB__Black", "color": "Black", "storage": "256 GB", "price": 3249,
"compareAtPrice": null, "onDeal": false, "inStock": true },
{ "id": "256 GB__Sage", "color": "Sage", "storage": "256 GB", "price": 3249,
"compareAtPrice": null, "onDeal": false, "inStock": true }
]
}
GET /health
Returns { "ok": true } when the service is up. No key needed.
JavaScript example (server side)
const res = await fetch('https://api.revio.me/v1/products/iphone-17', {
headers: { 'x-api-key': process.env.REVIO_API_KEY },
})
if (!res.ok) throw new Error(`Revio API ${res.status}`)
const product = await res.json()
const black256 = product.variants.find((v) => v.color === 'Black' && v.storage === '256 GB')
console.log(black256.price, product.currency) // 3249 'QAR'
Response fields
Product
| Field | Type | Meaning |
|---|---|---|
id | string | Permanent product id, used in /v1/products/{id} |
url | string | The product's page on revio.me |
name, brand, tagline | string | As shown on revio.me. tagline may be empty |
description | string | Plain text, detail only. May be empty |
category | string | phone, laptop, tablet, watch or other |
condition | string | null | new, open_box, refurbished, pre_owned, or null if not set |
currency | string | Always QAR |
purchasable | boolean | At least one option is in stock and can be bought now |
onDeal | boolean | A deal is lowering at least one price right now |
priceFrom | number | null | Lowest price among in-stock options, or among all options if none is in stock |
compareAtPriceFrom | number | null | The struck-through "was" price for that option, if any |
image | string | null | Main image URL (list only) |
images | array | { url, alt }, the first one is the main image (detail only) |
colors | array | Names in the list. In the detail: { name, hex, image }, where image is that colour's photo or null |
storages | array | Labels in the list. In the detail: one entry per storage size, cheapest first (below) |
variants | array | Detail only: every colour × storage combination (below) |
Storage (detail)
| Field | Type | Meaning |
|---|---|---|
label | string | e.g. 256 GB |
price | number | Base price for this size in QAR. A colour can cost more, so use variants for the exact price |
compareAtPrice | number | null | Struck-through "was" price |
onDeal | boolean | This size is on a deal |
inStock | boolean | At least one colour in this size is in stock |
Variant (detail)
| Field | Type | Meaning |
|---|---|---|
id | string | Stable id for this combination |
color | string | null | Colour name, null if the product has no colours |
storage | string | Storage label |
price | number | The price the customer pays for this exact combination, in QAR, including any deal |
compareAtPrice | number | null | Struck-through "was" price; only present when higher than price |
onDeal | boolean | The price is a deal price |
inStock | boolean | Can be bought right now |
Errors
Errors return a JSON body like { "error": "not_found" }.
| Status | error | When |
|---|---|---|
| 400 | invalid_handle | The product id isn't valid: only lowercase letters, numbers and hyphens |
| 401 | unauthorized | The x-api-key header is missing or wrong |
| 404 | not_found | No such product, or it is no longer for sale |
| 500 | internal_error | Something went wrong on our side. Retry after a short wait |
Good to know
- Freshness: price and stock changes appear within about a minute.
- Prices are whole QAR, with no decimals or VAT breakdown.
- Products come and go. A product that returns
404has been removed from sale; drop it on your side. - Images are public URLs you can show directly.
- Be gentle: refreshing the full list every few minutes is plenty. Please don't poll every second.