---
title: "Best Price Guarantee: ask for a hotel offer at a lower price found elsewhere"
method: POST
path: "/v1/best_price_guarantee"
tags: ["Hotels"]
---

# Best Price Guarantee: ask for a hotel offer at a lower price found elsewhere

`POST /v1/best_price_guarantee`

## Request

- Base URL: `https://api.gojinko.com`
- URL: `https://api.gojinko.com/v1/best_price_guarantee`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Submit a hotel offer from `POST /v1/hotel_search` with the lower price the traveller found for the same stay on another site: the link, a screenshot address and the total payable at booking, in the currency of the offer. The submission is reviewed in the background and this call answers `pending` with an `id`, or the result when `wait_seconds` let it finish in time. The answer carries the state of the request in `status`: `pending` while the review runs, then `offered` with the new offer, or `declined` with the reason. A decline is a 200: it is an answer, not a failure of the call. An offered result is a NEW offer id to add to a trip; the submitted offer is left as it was. Jinko enables Best Price Guarantee per account: a key it is not enabled for is answered HTTP 200 `status: declined` with `decline.reason: feature_disabled`.

## Request body

- BestPriceGuaranteeRequest
  - `product` 'hotel', required: The kind of product the request is about. Only `hotel` exists today.
  - `objective` 'price_parity': What is asked for. `price_parity` (the default, and the only value today) asks for the reference price, nothing lower.
  - `trip_item_token` string, required: The hotel offer the traveller compared: `hotels[].offers[].trip_item_token` from `POST /v1/hotel_search`. It names the hotel, the dates, the party and the rate. An offer is kept for 75 minutes after the search that returned it.
  - `reference` BestPriceGuaranteeReference, required
    - `url` string, required: The https link to the page where the traveller saw the lower price. It must be on a site accepted as a reference; another site is answered `declined` with reason `reference_source_not_allowed`.
    - `screenshot_url` string: An https address a screenshot of that page can be downloaded from. Required on most accounts: a submission without it is then answered `declined` with reason `reference_invalid`.
    - `total` string, required: The total payable AT BOOKING on that page, as a plain decimal string: no currency symbol, no thousands separator, at most the decimal places of `currency`. Taxes payable at the property are not part of it.
    - `currency` string, required: The ISO 4217 currency of `total`. It must be the currency of the offer being compared (`total_amount_money.currency` of the offer in `hotel_search`). A price in another currency is answered `declined` with reason `currency_mismatch`; nothing is converted.
  - `wait_seconds` integer: How long this call waits for the result before answering, 0–20 seconds (default 0: answer at once). It only decides when the call returns; the review continues either way, and a call that waited without a result answers `pending`.

## Response `200`

The state of the request

- BestPriceGuaranteeResponse
  - `id` string: Identifies the request; read its result with `GET /v1/best_price_guarantee/{id}`. Absent when the submission was declined before being recorded (`feature_disabled`, an unknown product).
  - `status` string, required: `pending`: the review is still running — read the request again; this is not a decline. It can take up to a few minutes when the reference page is checked. `offered`: `offer` holds the new offer. `declined`: no offer, see `decline.reason`. `expired`: an offer was made and not used before `expires_at`. Treat any other value as `pending`.
  - `poll_after_seconds` integer: Present while `status` is `pending`: a suggested pause before reading again.
  - `offer` BestPriceGuaranteeOffer
    - `offer_id` string, required: Deprecated: use `trip_item_token` instead. Same value.
    - `trip_item_token` string, required: The new offer. Pass it as `add_item.trip_item_token` to `POST /v1/trip`, then check out as for any hotel offer. A trip that holds it can hold nothing else: start a new trip, or send `remove_item` for the offer it replaces together with `add_item` in one call. Adding it beside another item is refused with 409.
    - `price_money` object, required: What the new offer costs, payable at booking: the price matched to the reference. The price at checkout can move with the supplier.
      - `value` integer, required: Integer amount in MINOR units at the ISO 4217 digits of `currency`: divide by 10 ** decimal_places to get the amount. Signed where the field says so (a price change delta).
      - `currency` string, required: ISO 4217 currency code.
      - `decimal_places` integer, required: The ISO 4217 digits of `currency` (2 for USD/EUR, 0 for JPY/KRW, 3 for BHD/KWD), and the scale of `value`.
      - `display` string, required: The same figure as a string ready to show: the ISO 4217 code, a space, then the amount at `decimal_places`, e.g. "USD 412.50". Show this; compute with `value`.
    - `original` object, required: The offer the new one replaces, and its standard price.
      - `kind` string, required: How the Jinko product was named in the request. `offer`: a hotel search offer, in `trip_item_token`. Other kinds may be added; read the fields that kind names.
      - `trip_item_token` string: The offer that was submitted. Present when `kind` is `offer`.
      - `offer_id` string: Deprecated: use `trip_item_token` instead. Same value.
      - `total_money` object, required: The standard price of the same rate at the time of the review. It can be lower than the price the earlier search showed for the submitted offer: a search for one hotel can price a rate lower than an area search did.
        - `value` integer, required: Integer amount in MINOR units at the ISO 4217 digits of `currency`: divide by 10 ** decimal_places to get the amount. Signed where the field says so (a price change delta).
        - `currency` string, required: ISO 4217 currency code.
        - `decimal_places` integer, required: The ISO 4217 digits of `currency` (2 for USD/EUR, 0 for JPY/KRW, 3 for BHD/KWD), and the scale of `value`.
        - `display` string, required: The same figure as a string ready to show: the ISO 4217 code, a space, then the amount at `decimal_places`, e.g. "USD 412.50". Show this; compute with `value`.
    - `reference` object, required: The reference the offer was reviewed against.
      - `total_money` object, required: The reference price as submitted.
        - `value` integer, required: Integer amount in MINOR units at the ISO 4217 digits of `currency`: divide by 10 ** decimal_places to get the amount. Signed where the field says so (a price change delta).
        - `currency` string, required: ISO 4217 currency code.
        - `decimal_places` integer, required: The ISO 4217 digits of `currency` (2 for USD/EUR, 0 for JPY/KRW, 3 for BHD/KWD), and the scale of `value`.
        - `display` string, required: The same figure as a string ready to show: the ISO 4217 code, a space, then the amount at `decimal_places`, e.g. "USD 412.50". Show this; compute with `value`.
      - `verified` boolean, required: `true` when Jinko read the reference page and it showed the same stay at or under the submitted total.
    - `saving_money` object, required: `original.total_money` minus `price_money`: the saving against the current standard price. Zero when that price was already at or below the reference.
      - `value` integer, required: Integer amount in MINOR units at the ISO 4217 digits of `currency`: divide by 10 ** decimal_places to get the amount. Signed where the field says so (a price change delta).
      - `currency` string, required: ISO 4217 currency code.
      - `decimal_places` integer, required: The ISO 4217 digits of `currency` (2 for USD/EUR, 0 for JPY/KRW, 3 for BHD/KWD), and the scale of `value`.
      - `display` string, required: The same figure as a string ready to show: the ISO 4217 code, a space, then the amount at `decimal_places`, e.g. "USD 412.50". Show this; compute with `value`.
    - `expires_at` string, required: Until when the new offer can be added to a trip (RFC 3339, UTC). At most 30 minutes after the review.
  - `decline` object: Present when `status` is `declined`.
    - `reason` string, required: Why there is no offer. The reasons known today are listed here; the set grows, so treat a reason that is not listed as "no offer". `feature_disabled`: Best Price Guarantee is not enabled for this key. `product_not_found`: the offer is not known, or older than 75 minutes — search again. `product_not_supported`: not a single-room hotel offer from a search. `rate_unavailable`: the same room, board and cancellation terms could not be found again — search again and resubmit. `reference_source_not_allowed`, `reference_invalid`, `currency_mismatch`: the reference cannot be used as submitted. `price_cannot_be_matched`: this price cannot be offered for this rate. `reference_not_lower`: the current price of this rate is already at or below the reference. After either of these two, search the hotel alone (`hotel_ids`) to get its current price: it can be lower than the price the earlier search showed. `objective_not_supported`: the requested objective is not available. `temporarily_unavailable`, `timeout`: the review did not complete — submitting again may succeed. Reasons from the check of the reference page, each with a specific `decline.detail`: `hotel_mismatch`: the page is for another hotel; `stay_mismatch`: the link or the page is for other dates or another number of guests, so it cannot be compared; `conditions_mismatch`: the page sells the stay only with another room, board or cancellation terms; `reference_mismatch`: the page shows a higher total for the stay than the reference submitted.
    - `detail` string: What the check of the reference page found, when the decline comes from it. Written for the traveller: pass it on as it is.

## Other responses

- `400`: Bad request
- `401`: Authentication required
- `402`: Payment required — organization balance exhausted
- `404`: Resource not found
- `409`: The operation conflicts with the current state of the resource
- `410`: The resource this request names no longer exists
- `422`: Validation error
- `429`: Rate limit or quota exceeded
- `502`: The travel provider rejected the request, or an upstream call failed
- `503`: No travel provider can serve the request right now
- `504`: The travel provider did not answer in time

---

[API](https://skmtc.dev/gojinko/apis/jinko-public-api.md) - [All operations](https://skmtc.dev/gojinko/apis/jinko-public-api/llms.txt) - [OpenAPI document](https://skmtc.dev/gojinko/apis/jinko-public-api/revisions/ac5046767e4c?raw)
