# Rakuten

Rakuten Ichiba (rakuten.co.jp) product and offer data. Rakuten is a mall of independent
shops: a listing belongs to one shop, and there is no aggregate product page — so the
**cross-shop offer list comes from the `gtin` key**, which returns every shop's offer for
a barcode in one request, sorted cheapest-first including shipping.

> **Rolling out.** Rakuten is onboarding now and is not yet enabled by default on new
accounts. [Contact us](https://kwery.co/contact) to be enabled as it goes live — the API
shape documented on this page is final and will not change.


## Supported countries 

`country` accepts: `jp`

Rakuten Ichiba is a single Japanese storefront (rakuten.co.jp) — there are no per-country
domains. Prices are in JPY.

## Keys 

| Key | Values | Description |
|  --- | --- | --- |
| `gtin` | JAN / EAN / GTIN | **The flagship path** — one request returns the full cross-shop offer list for the barcode, cheapest first including shipping. |
| `term` | Free text | Keyword search — returns a list of result items. |
| `id` | Rakuten listing ID | One shop's listing. The ID is `<shopUrlCode>/<manageNumber>` and **contains a slash**, e.g. `beauty1982/10000308`. |


## Topics 

| Topic | Description |
|  --- | --- |
| `search` (default) | The standard lookup for every key. |
| `product` | Direct listing fetch for a known `id` (skips the search leg). |


There is no `search_and_offers` topic on Rakuten: because every listing is a single
shop's offer, the offer list **is** the `gtin` search — nothing extra to fetch.

## Response 

Content differs by key (see [Sources overview](/sources#how-to-read-the-field-tables) for
the shared conventions):

**`key: gtin`** — the cross-shop offer list: `product_id`, `gtin`, `name`, `type`
(`"direct_offer"` — an offer list, not a product page), `offers_count` (offers
returned — page 1), `total_offers_count` (the full catalogue count on Rakuten, which may far
exceed `offers_count`), `currency`, `price_min` / `price_avg` / `price_max`, and `offers[]` —
cheapest first by landed total.

`product_id` is always `null` for a `gtin` lookup: Rakuten Ichiba has no cross-shop product id
for a barcode — each shop lists the item under its own id. The addressable ids are
per-offer: `offers[].id`, formatted `<shop>/<manageNumber>`, and any one of them can be
fetched on its own with `key: "id"`.

**`offers[]` fields** 

| Field | Description |
|  --- | --- |
| `offer_id` / `id` | The listing ID (`<shopUrlCode>/<manageNumber>`) — usable with `key: id`. `offer_id` carries the same value as `id` on every offer; it is an alias for offer-list contexts, not a second identifier. |
| `name` / `url` / `image_url` | The shop's listing title, URL, and image. |
| `price` / `currency` | Item price, JPY. |
| `shipping` / `is_free_shipping` / `total` | Shipping cost, free-shipping flag, and the landed total the list is sorted by. |
| `delivery_days` / `delivery_text` | Delivery estimate, where the shop states one. |
| `points` | Rakuten points granted on the purchase. |
| `seller_name` / `seller_id` / `shop_code` / `seller_url` / `shop_verified` | The shop's display name, Rakuten shop identifiers, URL, and verified flag. |
| `rating` / `rating_count` | The listing's review score and count. |
| `availability` | `in_stock` or `out_of_stock`, from the shop's sold-out flag and per-SKU stock. Unified field, see [Availability](/sources#availability). `stock` keeps the exact count where the shop tracks one. |


**`key: term`** — a search-results list: `offers[]` (the same per-row fields as
`offers[]` above, including the seller fields) plus `total_results`, `currency`, and
`price_min` / `price_avg` / `price_max`.

**`key: id`** — one shop's listing: `product_id`, `name`, `url`, `gtin` (the JAN — search
tiles never carry it, the listing page does), `price`, `currency`, `tax_rate`,
`postage_included`, `stock`, `is_available` / `is_sold_out`, `description`,
`category_id`, `attributes{}`, the seller fields, and `variants[]` for multi-SKU
listings — each variant with its own price and stock, with `price_min` / `price_max` /
`has_price_range` set when the listing prices a range.

## Example request 

cURL
```bash
curl -s https://api.kwery.co/job \
  -H "Authorization: Bearer $KWERY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"source":"rakuten","country":"jp","key":"gtin","values":["4954835136228"]}'
```

Node.js
```js
const res = await fetch('https://api.kwery.co/job', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.KWERY_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ source: 'rakuten', country: 'jp', key: 'gtin', values: ['4954835136228'] }),
});
const data = await res.json();
if (data.error) throw new Error(data.message);
console.log('job id:', data.job._id);
```

Python
```python
import os, requests

res = requests.post(
    "https://api.kwery.co/job",
    headers={"Authorization": f"Bearer {os.environ['KWERY_API_KEY']}"},
    json={"source": "rakuten", "country": "jp", "key": "gtin", "values": ["4954835136228"]},
)
data = res.json()
if data.get("error"):
    raise RuntimeError(data["message"])
print("job id:", data["job"]["_id"])
```

JavaScript
```js
const res = await fetch('https://api.kwery.co/job', {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${KWERY_API_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ source: 'rakuten', country: 'jp', key: 'gtin', values: ['4954835136228'] }),
});
const data = await res.json();
if (data.error) throw new Error(data.message);
console.log('job id:', data.job._id);
```

PHP
```php
<?php
$ch = curl_init('https://api.kwery.co/job');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST => true,
  CURLOPT_HTTPHEADER => [
    'Authorization: Bearer ' . getenv('KWERY_API_KEY'),
    'Content-Type: application/json',
  ],
  CURLOPT_POSTFIELDS => '{"source":"rakuten","country":"jp","key":"gtin","values":["4954835136228"]}',
]);
$data = json_decode(curl_exec($ch), true);
if ($data['error']) { throw new Exception($data['message']); }
echo 'job id: ' . $data['job']['_id'];
```

Go
```go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
)

func main() {
	body := []byte(`{"source":"rakuten","country":"jp","key":"gtin","values":["4954835136228"]}`)
	req, _ := http.NewRequest("POST", "https://api.kwery.co/job", bytes.NewBuffer(body))
	req.Header.Set("Authorization", "Bearer "+os.Getenv("KWERY_API_KEY"))
	req.Header.Set("Content-Type", "application/json")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	var data map[string]any
	json.NewDecoder(resp.Body).Decode(&data)
	fmt.Println("job:", data["job"])
}
```

Java
```java
var client = java.net.http.HttpClient.newHttpClient();
var request = java.net.http.HttpRequest.newBuilder()
    .uri(java.net.URI.create("https://api.kwery.co/job"))
    .header("Authorization", "Bearer " + System.getenv("KWERY_API_KEY"))
    .header("Content-Type", "application/json")
    .POST(java.net.http.HttpRequest.BodyPublishers.ofString(
        "{\"source\":\"rakuten\",\"country\":\"jp\",\"key\":\"gtin\",\"values\":[\"4954835136228\"]}"))
    .build();
var response = client.send(request, java.net.http.HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
```

C#
```csharp
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization",
    $"Bearer {Environment.GetEnvironmentVariable("KWERY_API_KEY")}");
var body = new StringContent(
    """{"source":"rakuten","country":"jp","key":"gtin","values":["4954835136228"]}""",
    System.Text.Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://api.kwery.co/job", body);
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

Ruby
```ruby
require 'net/http'
require 'json'

uri = URI('https://api.kwery.co/job')
req = Net::HTTP::Post.new(uri, {
  'Authorization' => "Bearer #{ENV['KWERY_API_KEY']}",
  'Content-Type' => 'application/json',
})
req.body = '{"source":"rakuten","country":"jp","key":"gtin","values":["4954835136228"]}'
data = JSON.parse(Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }.body)
raise data['message'] if data['error']
puts "job id: #{data['job']['_id']}"
```

## Example response 

Results are fetched with `GET /job/{id}/download` once the job is `finished`. The three
examples below are **real responses** — live rakuten.co.jp data captured 2026-09-16
through the shipped parser and shaped by the exact client path (`lib/public-result.js`).
Captured on a development rig while the source rolls out, which changes nothing about the
shape or the data: prices, shops, stock and EANs are genuine.

**`key: gtin`** — the flagship path: 45 offers across independent shops from one
request. To keep this page readable, `offers` shows the first 5 (the download contains
all 45; `total_offers: 245` is Rakuten's full catalogue count for this JAN):

```json
{
  "job_id": "<job id>",
  "status": "finished",
  "results": [
    {
      "query": {
        "source": "rakuten",
        "country": "jp",
        "key": "gtin",
        "value": "4954835136228",
        "topic": "search",
        "max_pages": 1,
        "max_age": 0
      },
      "content": {
        "product_id": null,
        "gtin": "4954835136228",
        "name": "送料無料!追跡あり! ミルボン ジェミールフラン メルティバターバーム 40g ■",
        "type": "direct_offer",
        "offers": [
          {
            "offer_id": "nacre-beaute/55436",
            "id": "nacre-beaute/55436",
            "name": "送料無料!追跡あり! ミルボン ジェミールフラン メルティバターバーム 40g ■",
            "url": "https://item.rakuten.co.jp/nacre-beaute/55436/",
            "image_url": "https://thumbnail.image.rakuten.co.jp/@0_mall/nacre-beaute/cabinet/12679755/12679766/imgrc0111183099.jpg",
            "price": 1657,
            "currency": "JPY",
            "seller_id": 380056,
            "seller_name": "Nacre Beaute",
            "shop_code": "nacre-beaute",
            "seller_url": "https://www.rakuten.co.jp/nacre-beaute/",
            "shop_verified": false,
            "shipping": 0,
            "is_free_shipping": true,
            "total": 1657,
            "delivery_days": null,
            "delivery_text": "営業日14時までの決済完了で当日発送!",
            "points": 15,
            "rating": 4.45,
            "rating_count": 712,
            "is_sold_out": false,
            "is_available": true
          },
          {
            "offer_id": "nihonbiyosoko/1038",
            "id": "nihonbiyosoko/1038",
            "name": "＼★当選確率1/2！最大100%ポイントバック★／ミルボン ジェミールフラン メルティバーム 40g 送料無料 MILBON アウトバス 洗い流さないトリートメント ハンドクリーム メルティバーム 40g",
            "url": "https://item.rakuten.co.jp/nihonbiyosoko/1038/",
            "image_url": "https://thumbnail.image.rakuten.co.jp/@0_mall/nihonbiyosoko/cabinet/13879622/13879892/imgrc0127916806.jpg",
            "price": 1660,
            "currency": "JPY",
            "seller_id": 427201,
            "seller_name": "日本美容倉庫 楽天市場店",
            "shop_code": "nihonbiyosoko",
            "seller_url": "https://www.rakuten.co.jp/nihonbiyosoko/",
            "shop_verified": false,
            "shipping": 0,
            "is_free_shipping": true,
            "total": 1660,
            "delivery_days": null,
            "delivery_text": "1〜2日以内に発送(休業日を除く)",
            "points": 15,
            "rating": 3.5,
            "rating_count": 2,
            "is_sold_out": false,
            "is_available": true
          },
          {
            "offer_id": "queenroom88/121097",
            "id": "queenroom88/121097",
            "name": "送料無料!ミルボン ジェミールフラン メルティバターバーム 40g",
            "url": "https://item.rakuten.co.jp/queenroom88/121097/",
            "image_url": "https://thumbnail.image.rakuten.co.jp/@0_mall/queenroom88/cabinet/11388266/11388996/imgrc0122285710.jpg",
            "price": 1661,
            "currency": "JPY",
            "seller_id": 432276,
            "seller_name": "Queen room 88",
            "shop_code": "queenroom88",
            "seller_url": "https://www.rakuten.co.jp/queenroom88/",
            "shop_verified": false,
            "shipping": 0,
            "is_free_shipping": true,
            "total": 1661,
            "delivery_days": null,
            "delivery_text": "営業日14時までのご注文確定で当日発送",
            "points": 15,
            "rating": 4.7,
            "rating_count": 130,
            "is_sold_out": false,
            "is_available": true
          },
          {
            "offer_id": "nacre-beaute/100020",
            "id": "nacre-beaute/100020",
            "name": "訳アリ【箱破損】送料無料!追跡あり! ミルボン ジェミールフラン メルティバターバーム 40g ■",
            "url": "https://item.rakuten.co.jp/nacre-beaute/100020/",
            "image_url": "https://thumbnail.image.rakuten.co.jp/@0_mall/nacre-beaute/cabinet/12679755/12679766/imgrc0111183099.jpg",
            "price": 1661,
            "currency": "JPY",
            "seller_id": 380056,
            "seller_name": "Nacre Beaute",
            "shop_code": "nacre-beaute",
            "seller_url": "https://www.rakuten.co.jp/nacre-beaute/",
            "shop_verified": false,
            "shipping": 0,
            "is_free_shipping": true,
            "total": 1661,
            "delivery_days": null,
            "delivery_text": "営業日14時までの決済完了で当日発送!",
            "points": 15,
            "rating": 0,
            "rating_count": 0,
            "is_sold_out": false,
            "is_available": true
          },
          {
            "offer_id": "kingroom33/55436",
            "id": "kingroom33/55436",
            "name": "送料無料!ミルボン ジェミールフラン メルティバターバーム 40g ■",
            "url": "https://item.rakuten.co.jp/kingroom33/55436/",
            "image_url": "https://thumbnail.image.rakuten.co.jp/@0_mall/kingroom33/cabinet/09670661/09683193/imgrc0096102051.jpg",
            "price": 1663,
            "currency": "JPY",
            "seller_id": 419720,
            "seller_name": "King Room 33",
            "shop_code": "kingroom33",
            "seller_url": "https://www.rakuten.co.jp/kingroom33/",
            "shop_verified": false,
            "shipping": 0,
            "is_free_shipping": true,
            "total": 1663,
            "delivery_days": null,
            "delivery_text": "営業日14時までの決済完了で当日発送!",
            "points": 15,
            "rating": 4.77,
            "rating_count": 740,
            "is_sold_out": false,
            "is_available": true
          }
        ],
        "offers_count": 45,
        "total_offers_count": 240,
        "currency": "JPY",
        "price_min": 1657,
        "price_max": 2125,
        "price_avg": 1881.62
      },
      "success": true,
      "updated_at": "2026-09-16T08:30:55.752Z",
      "trust": {
        "score": 0.9,
        "components": {
          "identity": 1,
          "completeness": 0.5,
          "price_integrity": 1,
          "offer_contamination": 1,
          "freshness": 1
        },
        "flagged_offers": []
      },
      "served_from": "live",
      "observed_at": "2026-09-16T08:30:55.748Z"
    }
  ]
}
```

**`key: term`** — search returns result rows in `offers[]` plus `total_results`. First 2
of 45 items shown; note the items carry the same seller fields as offers:

```json
{
  "job_id": "<job id>",
  "status": "finished",
  "results": [
    {
      "query": {
        "source": "rakuten",
        "country": "jp",
        "key": "term",
        "value": "????",
        "topic": "search",
        "max_pages": 1,
        "max_age": 0
      },
      "content": {
        "offers": [
          {
            "offer_id": "gakouin/001-001-093",
            "id": "gakouin/001-001-093",
            "name": "まだ間に合う 敬老の日 プレゼント 食べ物 温めるだけ 70代 80代 焼き済！レンジで簡単 京都 老舗 【 西京焼き ギフトセット 】 西京漬 惣菜 詰め合わせ ギフトセット 魚 惣菜 おかず 高級 京都 老舗 焼き魚 詰合せ お歳暮 個包装 便利 ご飯のお供 9/18までのご注文9/21届け",
            "url": "https://item.rakuten.co.jp/gakouin/001-001-093/",
            "image_url": "https://thumbnail.image.rakuten.co.jp/@0_mall/gakouin/cabinet/event/k/keiro-mada2.jpg",
            "price": 3680,
            "currency": "JPY",
            "seller_id": 242981,
            "seller_name": "西京焼専門店 京都 雅幸胤",
            "shop_code": "gakouin",
            "seller_url": "https://www.rakuten.co.jp/gakouin/",
            "shop_verified": false,
            "shipping": 0,
            "is_free_shipping": true,
            "total": 3680,
            "delivery_days": null,
            "delivery_text": "9/17 13:00までの注文で最短9/19お届け",
            "points": 68,
            "rating": 4.45,
            "rating_count": 5982,
            "is_sold_out": false,
            "is_available": true
          },
          {
            "offer_id": "giftland-showa/07704-01",
            "id": "giftland-showa/07704-01",
            "name": "敬老の日 まだ間に合う プレゼント 内祝い ギフト 博多華味鳥 博多のご馳走 12点 お返し 食べ物 グルメ お中元 御中元 出産内祝い 食品 香典返し 結婚内祝い 法事 送料無料 高級 福岡 3000円 ご飯のお供 年配 高齢者 ソーシャルギフト対応 【敬老の日 9/21までにお届け可】",
            "url": "https://item.rakuten.co.jp/giftland-showa/07704-01/",
            "image_url": "https://thumbnail.image.rakuten.co.jp/@0_mall/giftland-showa/cabinet/event/11919624/11919628/07704-01_keiro_m1.jpg",
            "price": 3480,
            "currency": "JPY",
            "seller_id": 368616,
            "seller_name": "内祝いのギフトランドショーワ",
            "shop_code": "giftland-showa",
            "seller_url": "https://www.rakuten.co.jp/giftland-showa/",
            "shop_verified": false,
            "shipping": 0,
            "is_free_shipping": true,
            "total": 3480,
            "delivery_days": 2,
            "delivery_text": "最短9/18お届け",
            "points": 32,
            "rating": 4.66,
            "rating_count": 702,
            "is_sold_out": false,
            "is_available": true
          }
        ],
        "total_results": 87421672,
        "currency": "JPY",
        "price_min": 890,
        "price_max": 18980,
        "price_avg": 5123.33
      },
      "success": true,
      "updated_at": "2026-09-16T08:30:58.845Z",
      "trust": {
        "score": 0.9,
        "components": {
          "identity": 1,
          "completeness": 0.5,
          "price_integrity": 1,
          "offer_contamination": 1,
          "freshness": 1
        },
        "flagged_offers": []
      },
      "served_from": "live",
      "observed_at": "2026-09-16T08:30:58.842Z"
    }
  ]
}
```

**`key: id`** — one shop's listing, the typical single-SKU case (`variants: []`,
`has_price_range: false`). Multi-SKU listings instead fill `variants[]` — each with its
own price and stock — and set `has_price_range`:

```json
{
  "job_id": "<job id>",
  "status": "finished",
  "results": [
    {
      "query": {
        "source": "rakuten",
        "country": "jp",
        "key": "id",
        "value": "beauty1982/10000308",
        "topic": "search",
        "max_pages": 1,
        "max_age": 0
      },
      "content": {
        "product_id": "beauty1982/10000308",
        "name": "【正規品】 ミルボン ジェミールフラン メルティバターバーム 40g バーム",
        "url": "https://item.rakuten.co.jp/beauty1982/10000308/",
        "gtin": "4954835136228",
        "price": 2240,
        "price_min": 2240,
        "price_max": 2240,
        "has_price_range": false,
        "variants": [],
        "currency": "JPY",
        "tax_rate": 0.1,
        "postage_included": true,
        "seller_id": "406836",
        "seller_name": "beauty.美容専門店",
        "shop_code": "beauty1982",
        "seller_url": "https://www.rakuten.co.jp/beauty1982/",
        "image_url": "@0_mall/beauty1982/cabinet/compass1769056336.jpg",
        "description": "洗い流さないトリートメント。<br>",
        "category_id": "210695",
        "stock": 51,
        "is_available": true,
        "is_sold_out": false,
        "rating_count": 11,
        "attributes": {
          "カラー": "バター",
          "シリーズ名": "-",
          "ブランド名": "ミルボン",
          "メーカー型番": "-",
          "原産国／製造国": "日本",
          "総重量": "40 g",
          "総本数": "1",
          "対象": "ユニセックス",
          "代表カラー": "イエロー",
          "単品重量": "40 g",
          "保湿": "有",
          "ダメージケア": "有",
          "フケ・頭皮のかゆみ": "有",
          "プロ・サロン用": "有",
          "ボリュームアップ": "有",
          "サロン専売": "有",
          "発売年月日": "2023/11/24",
          "ブランド名（カナ）": "ミルボン"
        }
      },
      "success": true,
      "updated_at": "2026-09-16T08:15:40.648Z",
      "trust": {
        "score": 0.83,
        "components": {
          "identity": 0.7,
          "completeness": 0.5,
          "price_integrity": 1,
          "offer_contamination": 1,
          "freshness": 1
        },
        "flagged_offers": []
      },
      "served_from": "live",
      "observed_at": "2026-09-16T08:15:40.647Z"
    }
  ]
}
```

The `trust` block is explained in [Confidence score](/guides/trust); `served_from` and `observed_at` in [Audit & provenance](/guides/audit-and-provenance).