Punchout
The final step of using the Storefront API for Amazon Business is to add the product to the shopping cart. The simplest way of achieving that is to initiate an OCI punchout to the detail page on Amazon.
Right now, you cannot add the product/offer to the shopping cart directly. You must do so by performing a punchout to Amazon. We have simplified this process to reduce your efforts to a minimum.
In the future, you might be able to directly add a product/offer to the shopping cart. However, this comes with additional complexities regarding your order process. So, for now, using OCI punchout is the simplest option you can choose.
Prerequisites
To follow this tutorial, you will need:
- A Storefront installation with a properly configured connection to Amazon Business as described in the Setup guide.
- A process of creating access tokens as described in the Authorization guide.
Initiating the punchout process
Once again, we need to use an access token (YOUR_ACCESS_TOKEN) to
authenticate your request. You will also need to pass the
YOUR_PRODUCT_ID again to initiate the punchout process.
Finally, we will need a YOUR_HOOK_URL that we will use to return
the shopping cart to your system as it is returned by Amazon.
- cURL
- JavaScript
- C#
- Java
- Go
curl --request POST \
--header 'authorization: YOUR_ACCESS_TOKEN' \
--url 'https://YOUR_DOMAIN/api/v1/amazon/products/YOUR_PRODUCT_ID/punchout'
--data '{"callbackUrl": "YOUR_HOOK_URL"}'
var axios = require("axios").default;
var options = {
method: 'POST',
url: 'https://YOUR_DOMAIN/api/v1/amazon/products/YOUR_PRODUCT_ID/punchout',
headers: {
'content-type': 'application/json',
'authorization': 'bearer YOUR_ACCESS_TOKEN'
},
json: {
callbackUrl: YOUR_HOOK_URL,
name: "Joe Average",
shipTo: {
street: "...",
city: "...",
state: "...",
postalCode: "...",
countryCode: "...",
country: "..."
}
}
};
axios.request(options).then(function (response) {
console.log(response.data);
}).catch(function (error) {
console.error(error);
});
var client = new RestClient("https://YOUR_DOMAIN/api/v1/amazon/products/YOUR_PRODUCT_ID/punchout");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/json");
request.AddHeader("authorization", "bearer YOUR_ACCESS_TOKEN");
request.AddStringBody(`{"callbackUrl": "+YOUR_HOOK_URL+"}`, ContentType.Json)
IRestResponse response = client.Execute(request);
HttpResponse<String> response = Unirest.post("https://YOUR_DOMAIN/api/v1/amazon/products/YOUR_PRODUCT_ID/punchout")
.header("content-type", "application/json")
.header("authorization", "bearer YOUR_ACCESS_TOKEN")
.body("{\"callbackUrl\": "+YOUR_HOOK_URL+"}")
.asString();
package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
// Configure your URL
url := "https://YOUR_DOMAIN"
// Setup the request body
var data = struct {
CallbackURL string `json:"callbackUrl,omitempty"`
}{
CallbackURL: YOUR_HOOK_URL,
}
body, err := json.Marshal(data)
if err != nil {
panic(err)
}
requestBody := bytes.NewReader(body)
// Prepare HTTP request
req, err := http.NewRequest("POST", baseURL+"/api/v1/amazon/products/YOUR_PRODUCT_ID/punchout", requestBody)
if err != nil {
panic(err)
}
req.Header.Set("content-type", "application/json")
req.Header.Set("authorization", "bearer "+YOUR_ACCESS_TOKEN)
// Execute the request
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
// The HTTP response body will return JSON accordingly
body, err := io.ReadAll(req.Body)
if err != nil {
panic(err)
}
fmt.Println(resp)
fmt.Println(string(body))
}
Parameters
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string | true | ID of the product to punchout |
Request Body
The request body is a JSON object.
| Parameter | Type | Required | Description |
|---|---|---|---|
| callbackUrl | string | true | HOOK_URL of the OCI punchout process. This URL will always be used, even in failure; in other words, we try everything to pass control back to the caller. |
| name | string | false | Full name of the requester, e.g. "Joe Average". It is being used e.g. in shipping notifications |
| shipTo | object(Address) | false | Shipment address (see below). If it is not specified here, Amazon may fallback to using the default address of the group/organization, which more often than not is a bad idea. |
Example:
{
"callbackUrl": "https://example.com/oci/callback",
"name": "Joe Average",
"shipTo": {
"street": "525 Market St",
"city": "San Francisco",
"postalCode": "94105",
"state": "CA",
"countryCode": "US",
"country": "United States of America"
}
}
Shipment address
The parameters of the shipment address are the same as those in the cXML specification.
| Parameter | Description |
|---|---|
addressId | (optional) ID of the address. |
addressIdDomain | (optional) Domain of the address ID. |
street | (optional) Street. |
cityCode | (optional) City code. |
city | (optional) City name. |
stateCode | (optional) State code. |
state | (optional) State. |
postalCode | (optional) Postal code. |
countryCode | (optional) Country code, e.g. US. |
country | (optional) Country name. |
Response
If everything goes well, you will receive a successful HTTP response with
status 201 Created with a payload containing a URL that you can send to the
user agent to follow.
{
"redirectUrl": "https://www.amazon.com/eprocurement/initiate-clean-punchout/123-4567890-1234567"
}
Asking the user agent to redirect to this URL will bring the end-user to the
detail page of the product on Amazon Business. When the user adds the product
to the shopping cart and completes the punchout procedure, the product gets
returned to the HOOK_URL specified in callbackUrl as with any other
shop connected via OCI punchout.
Errors
In case of an error, you can use the HTTP status code and the response body to find out what went wrong.
Example:
{
"error": {
"code": 400,
"message": "Please check the request parameters.",
"details": [
"You must specify a callbackUrl in the body of the request."
]
}
}