Search live hotel inventory and rates
curl --request POST \
--url https://api.example.com/v1/hotel_search \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"city_name": "Paris",
"country_code": "fr",
"checkin": "2026-09-01",
"checkout": "2026-09-04",
"adults": 2,
"currency": "USD"
}
'import requests
url = "https://api.example.com/v1/hotel_search"
payload = {
"city_name": "Paris",
"country_code": "fr",
"checkin": "2026-09-01",
"checkout": "2026-09-04",
"adults": 2,
"currency": "USD"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
city_name: 'Paris',
country_code: 'fr',
checkin: '2026-09-01',
checkout: '2026-09-04',
adults: 2,
currency: 'USD'
})
};
fetch('https://api.example.com/v1/hotel_search', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v1/hotel_search",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'city_name' => 'Paris',
'country_code' => 'fr',
'checkin' => '2026-09-01',
'checkout' => '2026-09-04',
'adults' => 2,
'currency' => 'USD'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v1/hotel_search"
payload := strings.NewReader("{\n \"city_name\": \"Paris\",\n \"country_code\": \"fr\",\n \"checkin\": \"2026-09-01\",\n \"checkout\": \"2026-09-04\",\n \"adults\": 2,\n \"currency\": \"USD\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/v1/hotel_search")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"city_name\": \"Paris\",\n \"country_code\": \"fr\",\n \"checkin\": \"2026-09-01\",\n \"checkout\": \"2026-09-04\",\n \"adults\": 2,\n \"currency\": \"USD\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/hotel_search")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"city_name\": \"Paris\",\n \"country_code\": \"fr\",\n \"checkin\": \"2026-09-01\",\n \"checkout\": \"2026-09-04\",\n \"adults\": 2,\n \"currency\": \"USD\"\n}"
response = http.request(request)
puts response.read_body{
"hotels": [
{
"hotel_id": "lp1d2c3",
"name": "Hôtel Le Marais",
"address": "12 Rue de Rivoli",
"city": "Paris",
"country": "fr",
"star_rating": 4,
"category": "4 KEYS",
"lodging_type": "Aparthotel",
"rating": 8.6,
"review_count": 1243,
"main_photo": "https://static.cupid.travel/hotels/main.jpg",
"thumbnail": "https://static.cupid.travel/hotels/thumb.jpg",
"latitude": 48.8566,
"longitude": 2.3522,
"rooms": [
{
"room_id": "rm_1",
"room_name": "Superior Double",
"description": "<string>",
"requested_occupancy": 2,
"max_occupancy": 2,
"rates": [
{
"offer_id": "htl_2d67a7441c60e5de",
"board_type": "RO",
"board_name": "Room Only",
"total_amount": 1818.4,
"currency": "EUR",
"is_refundable": false,
"free_cancellation_until": "2026-08-18T10:00:00+02:00",
"cancellation_schedule": [
{
"cancel_time": "2026-08-18T10:00:00+02:00",
"amount": 606.13,
"currency": "EUR",
"type": "amount"
}
],
"taxes_breakdown": [
{
"amount": 164.49,
"currency": "EUR",
"description": "19, VAT National taxes on accommodation",
"included": true
}
],
"payment_types": [
"NUITEE_PAY"
]
}
]
}
]
}
],
"total": 87,
"warnings": [
"<string>"
],
"budget_filter": {
"max_budget_per_night": 150,
"currency": "EUR",
"nights": 3,
"pages_fetched": 2,
"catalog_exhausted": true,
"hotels_dropped": 34
}
}{
"error": {
"code": "BAD_REQUEST",
"message": "Malformed JSON in request body.",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "AUTH_REQUIRED",
"message": "Invalid or expired API key.",
"doc_url": "https://docs.gojinko.com/api-reference/authentication"
}
}{
"error": {
"code": "PAYMENT_REQUIRED",
"message": "Insufficient balance — this call costs $0.0150 and your organization has $0.0000 available. Top up at https://dashboard.gojinko.com/developers/billing/topup",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "CONFLICT",
"message": "an exchange is already in progress for this booking",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "BAD_REQUEST",
"message": "origins: origins is required; trip_type: trip_type is required",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit or quota exceeded.",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "UPSTREAM_REJECTED",
"message": "sabre-rest BargainFinderMaxRQ failed with status 400: 27131 - Number of connection locations exceeds maximum allowed",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "UPSTREAM_UNAVAILABLE",
"message": "All flight providers are temporarily unable to serve this search. Please retry later. Provider reasons: sabre-rest: provider temporarily closed; travelfusion: quota exhausted",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "UPSTREAM_TIMEOUT",
"message": "sabre-rest BargainFinderMaxRQ timed out after 30s",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}Hotels
hotel-search
Search live hotel inventory and rates
POST
/
v1
/
hotel_search
Search live hotel inventory and rates
curl --request POST \
--url https://api.example.com/v1/hotel_search \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"city_name": "Paris",
"country_code": "fr",
"checkin": "2026-09-01",
"checkout": "2026-09-04",
"adults": 2,
"currency": "USD"
}
'import requests
url = "https://api.example.com/v1/hotel_search"
payload = {
"city_name": "Paris",
"country_code": "fr",
"checkin": "2026-09-01",
"checkout": "2026-09-04",
"adults": 2,
"currency": "USD"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
city_name: 'Paris',
country_code: 'fr',
checkin: '2026-09-01',
checkout: '2026-09-04',
adults: 2,
currency: 'USD'
})
};
fetch('https://api.example.com/v1/hotel_search', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v1/hotel_search",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'city_name' => 'Paris',
'country_code' => 'fr',
'checkin' => '2026-09-01',
'checkout' => '2026-09-04',
'adults' => 2,
'currency' => 'USD'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v1/hotel_search"
payload := strings.NewReader("{\n \"city_name\": \"Paris\",\n \"country_code\": \"fr\",\n \"checkin\": \"2026-09-01\",\n \"checkout\": \"2026-09-04\",\n \"adults\": 2,\n \"currency\": \"USD\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/v1/hotel_search")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"city_name\": \"Paris\",\n \"country_code\": \"fr\",\n \"checkin\": \"2026-09-01\",\n \"checkout\": \"2026-09-04\",\n \"adults\": 2,\n \"currency\": \"USD\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/hotel_search")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"city_name\": \"Paris\",\n \"country_code\": \"fr\",\n \"checkin\": \"2026-09-01\",\n \"checkout\": \"2026-09-04\",\n \"adults\": 2,\n \"currency\": \"USD\"\n}"
response = http.request(request)
puts response.read_body{
"hotels": [
{
"hotel_id": "lp1d2c3",
"name": "Hôtel Le Marais",
"address": "12 Rue de Rivoli",
"city": "Paris",
"country": "fr",
"star_rating": 4,
"category": "4 KEYS",
"lodging_type": "Aparthotel",
"rating": 8.6,
"review_count": 1243,
"main_photo": "https://static.cupid.travel/hotels/main.jpg",
"thumbnail": "https://static.cupid.travel/hotels/thumb.jpg",
"latitude": 48.8566,
"longitude": 2.3522,
"rooms": [
{
"room_id": "rm_1",
"room_name": "Superior Double",
"description": "<string>",
"requested_occupancy": 2,
"max_occupancy": 2,
"rates": [
{
"offer_id": "htl_2d67a7441c60e5de",
"board_type": "RO",
"board_name": "Room Only",
"total_amount": 1818.4,
"currency": "EUR",
"is_refundable": false,
"free_cancellation_until": "2026-08-18T10:00:00+02:00",
"cancellation_schedule": [
{
"cancel_time": "2026-08-18T10:00:00+02:00",
"amount": 606.13,
"currency": "EUR",
"type": "amount"
}
],
"taxes_breakdown": [
{
"amount": 164.49,
"currency": "EUR",
"description": "19, VAT National taxes on accommodation",
"included": true
}
],
"payment_types": [
"NUITEE_PAY"
]
}
]
}
]
}
],
"total": 87,
"warnings": [
"<string>"
],
"budget_filter": {
"max_budget_per_night": 150,
"currency": "EUR",
"nights": 3,
"pages_fetched": 2,
"catalog_exhausted": true,
"hotels_dropped": 34
}
}{
"error": {
"code": "BAD_REQUEST",
"message": "Malformed JSON in request body.",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "AUTH_REQUIRED",
"message": "Invalid or expired API key.",
"doc_url": "https://docs.gojinko.com/api-reference/authentication"
}
}{
"error": {
"code": "PAYMENT_REQUIRED",
"message": "Insufficient balance — this call costs $0.0150 and your organization has $0.0000 available. Top up at https://dashboard.gojinko.com/developers/billing/topup",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "CONFLICT",
"message": "an exchange is already in progress for this booking",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "BAD_REQUEST",
"message": "origins: origins is required; trip_type: trip_type is required",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit or quota exceeded.",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "UPSTREAM_REJECTED",
"message": "sabre-rest BargainFinderMaxRQ failed with status 400: 27131 - Number of connection locations exceeds maximum allowed",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "UPSTREAM_UNAVAILABLE",
"message": "All flight providers are temporarily unable to serve this search. Please retry later. Provider reasons: sabre-rest: provider temporarily closed; travelfusion: quota exhausted",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "UPSTREAM_TIMEOUT",
"message": "sabre-rest BargainFinderMaxRQ timed out after 30s",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}Search live hotel inventory and nightly rates for a destination and stay window. It handles requests like “three nights in Lisbon next weekend for two adults” or “family room in Rome with one child in August”. Each result includes an
htl_* offer token you can hand to the trip tool to start a booking.
Hotel prices are already in major units.
rates[].total_amount,
taxes_breakdown[].amount and cancellation_schedule[].amount are plain
decimals with no decimal_places field — display them as-is, do not
divide. (Flight endpoints differ: they return minor-unit integers.) See
Money & prices.Authorizations
ApiKeyAuthBearerAuth
Body
application/json
Pattern:
^\d{4}-\d{2}-\d{2}$Pattern:
^\d{4}-\d{2}-\d{2}$Example:
"Paris"
Required string length:
2Required range:
0 < x <= 50Show child attributes
Show child attributes
Required range:
x >= 1Required range:
x >= 1Required string length:
2Required range:
1 <= x <= 5Required range:
1 <= x <= 5Required range:
1 <= x <= 5Page size — max hotels returned (the limit). Default 50.
Pagination offset — skip this many hotels at the upstream search. Default 0.
Required range:
x >= 0Keep only hotels whose cheapest per-night price (per room, in the request currency) is within this budget; qualifying hotels keep all their rates. Destination searches automatically scan deeper into the hotel catalog when too few hotels fit the budget. Prefer a larger max_results over offset paging when this is set.
Required range:
x > 0Example:
150
Show child attributes
Show child attributes
