Purchase
curl --request POST \
--url https://api.example.com/v1/tools/commerce/buy \
--header 'Content-Type: application/json' \
--data '
{
"product_url": "<string>",
"shipping_address": {
"first_name": "<string>",
"last_name": "<string>",
"street": "<string>",
"street2": "<string>",
"city": "<string>",
"state": "<string>",
"zip_code": "<string>",
"country": "<string>",
"phone": "<string>",
"email": "<string>"
},
"quantity": 123,
"variant_id": "<string>"
}
'import requests
url = "https://api.example.com/v1/tools/commerce/buy"
payload = {
"product_url": "<string>",
"shipping_address": {
"first_name": "<string>",
"last_name": "<string>",
"street": "<string>",
"street2": "<string>",
"city": "<string>",
"state": "<string>",
"zip_code": "<string>",
"country": "<string>",
"phone": "<string>",
"email": "<string>"
},
"quantity": 123,
"variant_id": "<string>"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
product_url: '<string>',
shipping_address: {
first_name: '<string>',
last_name: '<string>',
street: '<string>',
street2: '<string>',
city: '<string>',
state: '<string>',
zip_code: '<string>',
country: '<string>',
phone: '<string>',
email: '<string>'
},
quantity: 123,
variant_id: '<string>'
})
};
fetch('https://api.example.com/v1/tools/commerce/buy', 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/tools/commerce/buy",
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([
'product_url' => '<string>',
'shipping_address' => [
'first_name' => '<string>',
'last_name' => '<string>',
'street' => '<string>',
'street2' => '<string>',
'city' => '<string>',
'state' => '<string>',
'zip_code' => '<string>',
'country' => '<string>',
'phone' => '<string>',
'email' => '<string>'
],
'quantity' => 123,
'variant_id' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$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/tools/commerce/buy"
payload := strings.NewReader("{\n \"product_url\": \"<string>\",\n \"shipping_address\": {\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"street\": \"<string>\",\n \"street2\": \"<string>\",\n \"city\": \"<string>\",\n \"state\": \"<string>\",\n \"zip_code\": \"<string>\",\n \"country\": \"<string>\",\n \"phone\": \"<string>\",\n \"email\": \"<string>\"\n },\n \"quantity\": 123,\n \"variant_id\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
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/tools/commerce/buy")
.header("Content-Type", "application/json")
.body("{\n \"product_url\": \"<string>\",\n \"shipping_address\": {\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"street\": \"<string>\",\n \"street2\": \"<string>\",\n \"city\": \"<string>\",\n \"state\": \"<string>\",\n \"zip_code\": \"<string>\",\n \"country\": \"<string>\",\n \"phone\": \"<string>\",\n \"email\": \"<string>\"\n },\n \"quantity\": 123,\n \"variant_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/tools/commerce/buy")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"product_url\": \"<string>\",\n \"shipping_address\": {\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"street\": \"<string>\",\n \"street2\": \"<string>\",\n \"city\": \"<string>\",\n \"state\": \"<string>\",\n \"zip_code\": \"<string>\",\n \"country\": \"<string>\",\n \"phone\": \"<string>\",\n \"email\": \"<string>\"\n },\n \"quantity\": 123,\n \"variant_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_bodyCommerce
Purchase
Purchase a product from supported retailers
POST
/
v1
/
tools
/
commerce
/
buy
Purchase
curl --request POST \
--url https://api.example.com/v1/tools/commerce/buy \
--header 'Content-Type: application/json' \
--data '
{
"product_url": "<string>",
"shipping_address": {
"first_name": "<string>",
"last_name": "<string>",
"street": "<string>",
"street2": "<string>",
"city": "<string>",
"state": "<string>",
"zip_code": "<string>",
"country": "<string>",
"phone": "<string>",
"email": "<string>"
},
"quantity": 123,
"variant_id": "<string>"
}
'import requests
url = "https://api.example.com/v1/tools/commerce/buy"
payload = {
"product_url": "<string>",
"shipping_address": {
"first_name": "<string>",
"last_name": "<string>",
"street": "<string>",
"street2": "<string>",
"city": "<string>",
"state": "<string>",
"zip_code": "<string>",
"country": "<string>",
"phone": "<string>",
"email": "<string>"
},
"quantity": 123,
"variant_id": "<string>"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
product_url: '<string>',
shipping_address: {
first_name: '<string>',
last_name: '<string>',
street: '<string>',
street2: '<string>',
city: '<string>',
state: '<string>',
zip_code: '<string>',
country: '<string>',
phone: '<string>',
email: '<string>'
},
quantity: 123,
variant_id: '<string>'
})
};
fetch('https://api.example.com/v1/tools/commerce/buy', 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/tools/commerce/buy",
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([
'product_url' => '<string>',
'shipping_address' => [
'first_name' => '<string>',
'last_name' => '<string>',
'street' => '<string>',
'street2' => '<string>',
'city' => '<string>',
'state' => '<string>',
'zip_code' => '<string>',
'country' => '<string>',
'phone' => '<string>',
'email' => '<string>'
],
'quantity' => 123,
'variant_id' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$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/tools/commerce/buy"
payload := strings.NewReader("{\n \"product_url\": \"<string>\",\n \"shipping_address\": {\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"street\": \"<string>\",\n \"street2\": \"<string>\",\n \"city\": \"<string>\",\n \"state\": \"<string>\",\n \"zip_code\": \"<string>\",\n \"country\": \"<string>\",\n \"phone\": \"<string>\",\n \"email\": \"<string>\"\n },\n \"quantity\": 123,\n \"variant_id\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
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/tools/commerce/buy")
.header("Content-Type", "application/json")
.body("{\n \"product_url\": \"<string>\",\n \"shipping_address\": {\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"street\": \"<string>\",\n \"street2\": \"<string>\",\n \"city\": \"<string>\",\n \"state\": \"<string>\",\n \"zip_code\": \"<string>\",\n \"country\": \"<string>\",\n \"phone\": \"<string>\",\n \"email\": \"<string>\"\n },\n \"quantity\": 123,\n \"variant_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/tools/commerce/buy")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"product_url\": \"<string>\",\n \"shipping_address\": {\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"street\": \"<string>\",\n \"street2\": \"<string>\",\n \"city\": \"<string>\",\n \"state\": \"<string>\",\n \"zip_code\": \"<string>\",\n \"country\": \"<string>\",\n \"phone\": \"<string>\",\n \"email\": \"<string>\"\n },\n \"quantity\": 123,\n \"variant_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_bodyOverview
Places an order with Amazon, Shopify stores, and other supported retailers, shipped to a US address. It takes two calls:- The first call returns a
402with the quote andquote_id. - The second call, with
X-Quote-IDandpayment-signatureheaders, places the order.
Retrying safely
The second call is idempotent. If its response is lost, send it again with the sameX-Quote-ID: the API returns the original 202 with the header Idempotent-Replay: true, settles no second payment and places no second order. This holds for 24 hours, for wallet-signed and credit-funded purchases alike.
An Idempotency-Key header (1 to 255 letters, digits, _ . : -) is honoured on top: the same key with the same purchase replays, even under a new quote. It is bound to product_url, shipping_address, quantity and variant_id: the same key with a different purchase returns 422 idempotency_key_reuse. A quote is never paid twice, whatever key each attempt carries. The first call never claims a key and repeats freely.
The 202 returns the key in effect as idempotency_key. A retry can also meet:
409 request_in_flight: the first attempt is still running. Retry shortly with the same headers.503 quote_store_unavailable(withRetry-After): the quote could not be claimed and no order was placed. Wallet-signed: the payment has settled. Sign no new authorization and do not re-present this one (refused with409 payment_already_used); contact support with theX-Quote-ID. Credit-funded: nothing was charged; credits are debited after the claim. Retry with the sameX-Quote-ID; a400 quote_already_usedthen means the lost attempt consumed the quote unpaid: request a new quote.400 quote_already_used: an earlier attempt consumed the quote. Do not re-quote and pay again; check that attempt’srequest_idfirst.
Request Body
string
required
Product URL (Amazon, Shopify, etc.)
object
required
Delivery address
Show properties
Show properties
string
required
First name
string
required
Last name
string
required
Street address
string
Apartment, suite, etc.
string
required
City
string
required
State/Province code
string
required
ZIP/Postal code
string
Country code. Must be
US; only US shipping is supported.string
required
Phone number
string
Email for order updates
number
default:1
Quantity
string
Product variant ID, if applicable
Response (402 - Quote)
The first call returns the quote:{
"error": "payment_required",
"context": {
"quote_id": "quote_abc123",
"product_title": "Wireless Headphones",
"subtotal": "79.99",
"shipping": "5.99",
"tax": "7.20",
"fee": "2.50",
"total": "95.68"
},
"payment_request": {
"chain_id": 8453,
"token_address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"amount": "95.68",
"recipient": "0x..."
}
}
Response (202 - Order Submitted)
The second call, with payment, returns:{
"request_id": "req_xyz789",
"receipt_id": "rcpt_abc123",
"status": "processing",
"message": "Order submission in progress. Check status with /v1/requests/{id}.",
"idempotency_key": "quote:quote_abc123"
}
Job Result
{
"status": "completed",
"result": {
"status": "order_submitted",
"order_id": "114-1234567-8901234",
"order_status": "placed",
"tracking_url": "https://...",
"effect_evidence": {
"vendor": "rye",
"ref": "<the checkout intent id Rye returned>",
"kind": "rye_checkout_intent_id"
},
"provider": "amazon"
}
}
effect_evidence is the executing vendor’s own identifier for the submission, or null when it returned none; GET /v1/requests/:id also surfaces it top-level.
SDK Usage
const order = await agent.commerceBuy({
product_url: "https://amazon.com/dp/B07ZPC9QD4",
shipping_address: {
first_name: "John",
last_name: "Doe",
street: "123 Main St",
city: "San Francisco",
state: "CA",
zip_code: "94102",
country: "US",
phone: "4155550100",
},
quantity: 1,
maxCost: 100, // Optional: fail if total exceeds this
});
console.log(`Order ID: ${order.order_id}`);
console.log(`Status: ${order.order_status}`);
console.log(`Tracking: ${order.tracking_url}`);
Limitations
Only US shipping addresses are supported. A non-US
country code returns
a 400 error.Supported Retailers
- Amazon (US)
- Shopify stores
- Many more US-based retailers