Exchange a hosted-checkout handoff
curl --request POST \
--url https://api.craveup.com/api/v1/storefront/locations/{locationId}/carts/{cartId}/checkout-handoffs/exchange \
--header 'Idempotency-Key: <idempotency-key>' \
--header 'X-Checkout-Handoff: <api-key>'import requests
url = "https://api.craveup.com/api/v1/storefront/locations/{locationId}/carts/{cartId}/checkout-handoffs/exchange"
headers = {
"Idempotency-Key": "<idempotency-key>",
"X-Checkout-Handoff": "<api-key>"
}
response = requests.post(url, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Idempotency-Key': '<idempotency-key>', 'X-Checkout-Handoff': '<api-key>'}
};
fetch('https://api.craveup.com/api/v1/storefront/locations/{locationId}/carts/{cartId}/checkout-handoffs/exchange', 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.craveup.com/api/v1/storefront/locations/{locationId}/carts/{cartId}/checkout-handoffs/exchange",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Idempotency-Key: <idempotency-key>",
"X-Checkout-Handoff: <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"
"net/http"
"io"
)
func main() {
url := "https://api.craveup.com/api/v1/storefront/locations/{locationId}/carts/{cartId}/checkout-handoffs/exchange"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("X-Checkout-Handoff", "<api-key>")
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.craveup.com/api/v1/storefront/locations/{locationId}/carts/{cartId}/checkout-handoffs/exchange")
.header("Idempotency-Key", "<idempotency-key>")
.header("X-Checkout-Handoff", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.craveup.com/api/v1/storefront/locations/{locationId}/carts/{cartId}/checkout-handoffs/exchange")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["X-Checkout-Handoff"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"cart": {
"id": "cart_123",
"locationId": "loc_456def",
"status": "OPEN",
"lockedAt": null,
"discountCode": "SAVE10",
"currency": "usd",
"fulfilmentMethod": "pickup",
"statementDescriptor": "CRAVE*Downtown Pizza Co",
"pickupType": "ASAP",
"orderDate": "2024-11-12",
"orderTime": "18:30",
"totalQuantity": 3,
"subTotal": "3600",
"subTotalFormatted": "$36.00",
"discountTotal": "0.00",
"discountTotalFormatted": "$0.00",
"waiterTipTotal": "540",
"waiterTipTotalFormatted": "$5.40",
"taxTotal": "280",
"taxTotalFormatted": "$2.80",
"taxAndFeeTotal": "320",
"taxAndFeeTotalFormatted": "$3.20",
"serviceFeeTotal": "120",
"serviceFeeTotalFormatted": "$1.20",
"paymentProcessingFeeTotal": "40",
"paymentProcessingFeeTotalFormatted": "$0.40",
"applicationFeeTotal": "0.00",
"applicationFeeTotalFormatted": "$0.00",
"netSalesTotal": "3600",
"netSalesTotalFormatted": "$36.00",
"fulfillmentMethodFeeTotal": "0.00",
"fulfillmentMethodFeeTotalFormatted": "$0.00",
"orderTotalWithServiceFee": "4460",
"orderTotalWithServiceFeeFormatted": "$44.60",
"orderTotalWithServiceFeeAmount": 4460,
"orderTotal": "4040",
"orderTotalFormatted": "$40.40",
"enterpriseFeeTotal": "0.00",
"enterpriseFeeTotalFormatted": "$0.00",
"subTotalWithoutDiscount": "3600",
"subTotalWithoutDiscountFormatted": "$36.00",
"restaurantDisplayName": "Downtown Pizza Co",
"deliveryInfo": {
"addressString": "123 Market Street, San Francisco, CA 94105",
"addressData": {}
},
"tableServiceInfo": {
"tableNumber": "A5"
},
"roomServiceInfo": {
"lastName": "Smith",
"roomNumber": "1203"
},
"fees": {
"enterpriseFeeRate": "0.0000",
"enterpriseFeeFix": "0.00",
"serviceFeeRate": "0.0250",
"serviceFeeFix": "0.00",
"taxRate": "0.0775",
"tipRate": "0.0000",
"fulfillmentMethodFeeFix": "0.00",
"fulfillmentMethodFeeRate": "0.0000",
"paymentProcessingFeeRate": "0.0290",
"paymentProcessingFeeFix": "0.30"
},
"metadata": {},
"fulfillmentIdentifier": null
},
"cartAccessToken": "<string>",
"merchantSlug": "<string>"
}{
"success": false,
"message": "Unauthorized access",
"code": "UNAUTHORIZED"
}Carts
Exchange a hosted-checkout handoff
Consumes the short-lived fragment handoff and rotates the cart capability into the hosted checkout origin. The response carries the verified merchant slug needed for customer authentication on the shared checkout host. Exact retries with the same Idempotency-Key replay the response; a different key is rejected after consumption.
POST
/
locations
/
{locationId}
/
carts
/
{cartId}
/
checkout-handoffs
/
exchange
Exchange a hosted-checkout handoff
curl --request POST \
--url https://api.craveup.com/api/v1/storefront/locations/{locationId}/carts/{cartId}/checkout-handoffs/exchange \
--header 'Idempotency-Key: <idempotency-key>' \
--header 'X-Checkout-Handoff: <api-key>'import requests
url = "https://api.craveup.com/api/v1/storefront/locations/{locationId}/carts/{cartId}/checkout-handoffs/exchange"
headers = {
"Idempotency-Key": "<idempotency-key>",
"X-Checkout-Handoff": "<api-key>"
}
response = requests.post(url, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Idempotency-Key': '<idempotency-key>', 'X-Checkout-Handoff': '<api-key>'}
};
fetch('https://api.craveup.com/api/v1/storefront/locations/{locationId}/carts/{cartId}/checkout-handoffs/exchange', 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.craveup.com/api/v1/storefront/locations/{locationId}/carts/{cartId}/checkout-handoffs/exchange",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Idempotency-Key: <idempotency-key>",
"X-Checkout-Handoff: <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"
"net/http"
"io"
)
func main() {
url := "https://api.craveup.com/api/v1/storefront/locations/{locationId}/carts/{cartId}/checkout-handoffs/exchange"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("X-Checkout-Handoff", "<api-key>")
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.craveup.com/api/v1/storefront/locations/{locationId}/carts/{cartId}/checkout-handoffs/exchange")
.header("Idempotency-Key", "<idempotency-key>")
.header("X-Checkout-Handoff", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.craveup.com/api/v1/storefront/locations/{locationId}/carts/{cartId}/checkout-handoffs/exchange")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["X-Checkout-Handoff"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"cart": {
"id": "cart_123",
"locationId": "loc_456def",
"status": "OPEN",
"lockedAt": null,
"discountCode": "SAVE10",
"currency": "usd",
"fulfilmentMethod": "pickup",
"statementDescriptor": "CRAVE*Downtown Pizza Co",
"pickupType": "ASAP",
"orderDate": "2024-11-12",
"orderTime": "18:30",
"totalQuantity": 3,
"subTotal": "3600",
"subTotalFormatted": "$36.00",
"discountTotal": "0.00",
"discountTotalFormatted": "$0.00",
"waiterTipTotal": "540",
"waiterTipTotalFormatted": "$5.40",
"taxTotal": "280",
"taxTotalFormatted": "$2.80",
"taxAndFeeTotal": "320",
"taxAndFeeTotalFormatted": "$3.20",
"serviceFeeTotal": "120",
"serviceFeeTotalFormatted": "$1.20",
"paymentProcessingFeeTotal": "40",
"paymentProcessingFeeTotalFormatted": "$0.40",
"applicationFeeTotal": "0.00",
"applicationFeeTotalFormatted": "$0.00",
"netSalesTotal": "3600",
"netSalesTotalFormatted": "$36.00",
"fulfillmentMethodFeeTotal": "0.00",
"fulfillmentMethodFeeTotalFormatted": "$0.00",
"orderTotalWithServiceFee": "4460",
"orderTotalWithServiceFeeFormatted": "$44.60",
"orderTotalWithServiceFeeAmount": 4460,
"orderTotal": "4040",
"orderTotalFormatted": "$40.40",
"enterpriseFeeTotal": "0.00",
"enterpriseFeeTotalFormatted": "$0.00",
"subTotalWithoutDiscount": "3600",
"subTotalWithoutDiscountFormatted": "$36.00",
"restaurantDisplayName": "Downtown Pizza Co",
"deliveryInfo": {
"addressString": "123 Market Street, San Francisco, CA 94105",
"addressData": {}
},
"tableServiceInfo": {
"tableNumber": "A5"
},
"roomServiceInfo": {
"lastName": "Smith",
"roomNumber": "1203"
},
"fees": {
"enterpriseFeeRate": "0.0000",
"enterpriseFeeFix": "0.00",
"serviceFeeRate": "0.0250",
"serviceFeeFix": "0.00",
"taxRate": "0.0775",
"tipRate": "0.0000",
"fulfillmentMethodFeeFix": "0.00",
"fulfillmentMethodFeeRate": "0.0000",
"paymentProcessingFeeRate": "0.0290",
"paymentProcessingFeeFix": "0.30"
},
"metadata": {},
"fulfillmentIdentifier": null
},
"cartAccessToken": "<string>",
"merchantSlug": "<string>"
}{
"success": false,
"message": "Unauthorized access",
"code": "UNAUTHORIZED"
}Authorizations
Short-lived one-time handoff read from the hosted checkout URL fragment and removed from browser history before exchange.
Headers
Response
Checkout handoff exchanged.
⌘I