curl --request POST \
--url https://api.gojinko.com/v1/hotel_cancel_commit \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"booking_ref": "JNK-H1ZK90",
"last_name": "Doe",
"quote": "svq_01J7ZR3M8FKX2P9C",
"acknowledged": {
"value": 25000,
"currency": "USD",
"decimal_places": 2
}
}
'import requests
url = "https://api.gojinko.com/v1/hotel_cancel_commit"
payload = {
"booking_ref": "JNK-H1ZK90",
"last_name": "Doe",
"quote": "svq_01J7ZR3M8FKX2P9C",
"acknowledged": {
"value": 25000,
"currency": "USD",
"decimal_places": 2
}
}
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({
booking_ref: 'JNK-H1ZK90',
last_name: 'Doe',
quote: 'svq_01J7ZR3M8FKX2P9C',
acknowledged: {value: 25000, currency: 'USD', decimal_places: 2}
})
};
fetch('https://api.gojinko.com/v1/hotel_cancel_commit', 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.gojinko.com/v1/hotel_cancel_commit",
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([
'booking_ref' => 'JNK-H1ZK90',
'last_name' => 'Doe',
'quote' => 'svq_01J7ZR3M8FKX2P9C',
'acknowledged' => [
'value' => 25000,
'currency' => 'USD',
'decimal_places' => 2
]
]),
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.gojinko.com/v1/hotel_cancel_commit"
payload := strings.NewReader("{\n \"booking_ref\": \"JNK-H1ZK90\",\n \"last_name\": \"Doe\",\n \"quote\": \"svq_01J7ZR3M8FKX2P9C\",\n \"acknowledged\": {\n \"value\": 25000,\n \"currency\": \"USD\",\n \"decimal_places\": 2\n }\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.gojinko.com/v1/hotel_cancel_commit")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"booking_ref\": \"JNK-H1ZK90\",\n \"last_name\": \"Doe\",\n \"quote\": \"svq_01J7ZR3M8FKX2P9C\",\n \"acknowledged\": {\n \"value\": 25000,\n \"currency\": \"USD\",\n \"decimal_places\": 2\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gojinko.com/v1/hotel_cancel_commit")
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 \"booking_ref\": \"JNK-H1ZK90\",\n \"last_name\": \"Doe\",\n \"quote\": \"svq_01J7ZR3M8FKX2P9C\",\n \"acknowledged\": {\n \"value\": 25000,\n \"currency\": \"USD\",\n \"decimal_places\": 2\n }\n}"
response = http.request(request)
puts response.read_body{
"operation": "svc_01J7ZR5Q2KME8V4T",
"state": "in_progress"
}{
"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/authentication/api-keys"
}
}{
"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": "NOT_FOUND",
"message": "booking not found"
}
}{
"error": {
"code": "CONFLICT",
"message": "Your acknowledged figure differs from the quote’s refund; nothing was cancelled. Show the customer `current.refund`, then commit again with `requote` (the same quote handle) and that figure."
},
"code": "quote_drift",
"requote": "svq_01J8AB4N7GLY3Q0D",
"current": {
"refund": {
"value": 20500,
"currency": "USD",
"decimal_places": 2
}
}
}{
"error": {
"code": "GONE",
"message": "The resource no longer exists.",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "BAD_REQUEST",
"message": "A required field is missing or invalid.",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "RATE_LIMITED",
"message": "Too many requests. Retry after the Retry-After delay.",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "UPSTREAM_REJECTED",
"message": "The request was declined for this offer. Try another offer.",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "UPSTREAM_UNAVAILABLE",
"message": "The service is temporarily unavailable. Retry after the Retry-After delay.",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "UPSTREAM_TIMEOUT",
"message": "The request timed out before a result was available. Retry the request.",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}hotel-cancel-commit
Cancel a hotel booking against a quote the customer accepted
curl --request POST \
--url https://api.gojinko.com/v1/hotel_cancel_commit \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"booking_ref": "JNK-H1ZK90",
"last_name": "Doe",
"quote": "svq_01J7ZR3M8FKX2P9C",
"acknowledged": {
"value": 25000,
"currency": "USD",
"decimal_places": 2
}
}
'import requests
url = "https://api.gojinko.com/v1/hotel_cancel_commit"
payload = {
"booking_ref": "JNK-H1ZK90",
"last_name": "Doe",
"quote": "svq_01J7ZR3M8FKX2P9C",
"acknowledged": {
"value": 25000,
"currency": "USD",
"decimal_places": 2
}
}
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({
booking_ref: 'JNK-H1ZK90',
last_name: 'Doe',
quote: 'svq_01J7ZR3M8FKX2P9C',
acknowledged: {value: 25000, currency: 'USD', decimal_places: 2}
})
};
fetch('https://api.gojinko.com/v1/hotel_cancel_commit', 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.gojinko.com/v1/hotel_cancel_commit",
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([
'booking_ref' => 'JNK-H1ZK90',
'last_name' => 'Doe',
'quote' => 'svq_01J7ZR3M8FKX2P9C',
'acknowledged' => [
'value' => 25000,
'currency' => 'USD',
'decimal_places' => 2
]
]),
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.gojinko.com/v1/hotel_cancel_commit"
payload := strings.NewReader("{\n \"booking_ref\": \"JNK-H1ZK90\",\n \"last_name\": \"Doe\",\n \"quote\": \"svq_01J7ZR3M8FKX2P9C\",\n \"acknowledged\": {\n \"value\": 25000,\n \"currency\": \"USD\",\n \"decimal_places\": 2\n }\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.gojinko.com/v1/hotel_cancel_commit")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"booking_ref\": \"JNK-H1ZK90\",\n \"last_name\": \"Doe\",\n \"quote\": \"svq_01J7ZR3M8FKX2P9C\",\n \"acknowledged\": {\n \"value\": 25000,\n \"currency\": \"USD\",\n \"decimal_places\": 2\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gojinko.com/v1/hotel_cancel_commit")
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 \"booking_ref\": \"JNK-H1ZK90\",\n \"last_name\": \"Doe\",\n \"quote\": \"svq_01J7ZR3M8FKX2P9C\",\n \"acknowledged\": {\n \"value\": 25000,\n \"currency\": \"USD\",\n \"decimal_places\": 2\n }\n}"
response = http.request(request)
puts response.read_body{
"operation": "svc_01J7ZR5Q2KME8V4T",
"state": "in_progress"
}{
"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/authentication/api-keys"
}
}{
"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": "NOT_FOUND",
"message": "booking not found"
}
}{
"error": {
"code": "CONFLICT",
"message": "Your acknowledged figure differs from the quote’s refund; nothing was cancelled. Show the customer `current.refund`, then commit again with `requote` (the same quote handle) and that figure."
},
"code": "quote_drift",
"requote": "svq_01J8AB4N7GLY3Q0D",
"current": {
"refund": {
"value": 20500,
"currency": "USD",
"decimal_places": 2
}
}
}{
"error": {
"code": "GONE",
"message": "The resource no longer exists.",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "BAD_REQUEST",
"message": "A required field is missing or invalid.",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "RATE_LIMITED",
"message": "Too many requests. Retry after the Retry-After delay.",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "UPSTREAM_REJECTED",
"message": "The request was declined for this offer. Try another offer.",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "UPSTREAM_UNAVAILABLE",
"message": "The service is temporarily unavailable. Retry after the Retry-After delay.",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}{
"error": {
"code": "UPSTREAM_TIMEOUT",
"message": "The request timed out before a result was available. Retry the request.",
"doc_url": "https://docs.gojinko.com/concepts/errors"
}
}quote handle and the acknowledged figure PLUS the same booking_ref, item_id and last_name the preview took: ownership is re-checked here rather than carried by the handle, so they have to be sent again. acknowledged is the refund the customer was shown, copied from the preview as it arrived (value and decimal_places included): if your figure differs from the still-live quote’s refund, the call is refused with 409 quote_drift. requote is that same quote’s handle and current.refund its figure. Show it to the customer, then commit again with that handle and figure. Nothing is cancelled. If the supplier’s policy moved since the quote, quote_drift has no requote; preview again. The other refusals are 409 quote_expired (run hotel_cancel_preview again), active_operation_exists (poll the active_operation when present instead of starting a second one), not_cancellable and funds_unavailable. Success does NOT mean the money has moved: cancelling at the supplier and refunding the customer are separate steps, so the answer is an operation handle to poll with POST /v1/hotel_cancel_status.Authorizations
Body
Jinko booking reference. Call get_booking first, then select its item_id for servicing.
1"JNK-A0AUR2"
The "svq_…" handle from a preceding POST /v1/hotel_cancel_preview. Binds this commit to the figures that quote reported.
"svq_01J7ZR3M8FKX2P9C"
The refund the customer was shown — copy the preview's refund.amount_money across. Copying the whole refund object, as older integrations do, is still accepted. All three of value (minor units), currency and decimal_places are REQUIRED: the platform compares this against the refund as it stands, and a figure whose scale is unstated cannot be compared. amount is not accepted in its place. Any other key, such as display or basis, is ignored. A mismatch against a still-live quote’s refund is answered 409 quote_drift. requote is that same quote’s handle and current.refund its figure. Show it to the customer, then commit again with that handle and figure. Nothing is cancelled.
Show child attributes
Show child attributes
Stable booked item ID from get_booking items[].item_id. Preserved across exchanges. Omit only when the booking has exactly one item of the requested domain; otherwise a 409 returns items to choose from.
0 < x <= 900719925474099142
Required for guest lookup. A credential that owns the booking may omit it; ownership is checked by the platform.
1"Doe"
Show child attributes
Show child attributes
Response
The cancellation was accepted and is running
The cancellation this call started ("svc_…"). Poll it with POST /v1/hotel_cancel_status; it is the only handle that reports how the supplier call and the refund ended.
"svc_01J7ZR5Q2KME8V4T"
Where the cancellation has got to. in_progress — running; keep polling. attention_required — stalled on something a person at Jinko has to resolve (reason names it); keep polling, and do not report it to the customer as a failure, because the booking may already be cancelled at the supplier. succeeded and failed are terminal: the supplier outcome and the money are both settled and nothing further will change.
in_progress, attention_required, succeeded, failed 