curl --request POST \
--url https://{base_url_domain}/api/global/v1/inventory/product-profiles \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Lightweight Parcel",
"conditions": {
"or": [
{
"and": [
{
"<=": [
{
"var": "weight"
},
{
"value": 15,
"unit": "lb"
}
]
}
]
}
]
},
"code": "lightweight_parcel"
}
'import requests
url = "https://{base_url_domain}/api/global/v1/inventory/product-profiles"
payload = {
"name": "Lightweight Parcel",
"conditions": { "or": [{ "and": [{ "<=": [
{ "var": "weight" },
{
"value": 15,
"unit": "lb"
}
] }] }] },
"code": "lightweight_parcel"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Lightweight Parcel',
conditions: {or: [{and: [{'<=': [{var: 'weight'}, {value: 15, unit: 'lb'}]}]}]},
code: 'lightweight_parcel'
})
};
fetch('https://{base_url_domain}/api/global/v1/inventory/product-profiles', 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://{base_url_domain}/api/global/v1/inventory/product-profiles",
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([
'name' => 'Lightweight Parcel',
'conditions' => [
'or' => [
[
'and' => [
[
'<=' => [
[
'var' => 'weight'
],
[
'value' => 15,
'unit' => 'lb'
]
]
]
]
]
]
],
'code' => 'lightweight_parcel'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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://{base_url_domain}/api/global/v1/inventory/product-profiles"
payload := strings.NewReader("{\n \"name\": \"Lightweight Parcel\",\n \"conditions\": {\n \"or\": [\n {\n \"and\": [\n {\n \"<=\": [\n {\n \"var\": \"weight\"\n },\n {\n \"value\": 15,\n \"unit\": \"lb\"\n }\n ]\n }\n ]\n }\n ]\n },\n \"code\": \"lightweight_parcel\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://{base_url_domain}/api/global/v1/inventory/product-profiles")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Lightweight Parcel\",\n \"conditions\": {\n \"or\": [\n {\n \"and\": [\n {\n \"<=\": [\n {\n \"var\": \"weight\"\n },\n {\n \"value\": 15,\n \"unit\": \"lb\"\n }\n ]\n }\n ]\n }\n ]\n },\n \"code\": \"lightweight_parcel\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://{base_url_domain}/api/global/v1/inventory/product-profiles")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Lightweight Parcel\",\n \"conditions\": {\n \"or\": [\n {\n \"and\": [\n {\n \"<=\": [\n {\n \"var\": \"weight\"\n },\n {\n \"value\": 15,\n \"unit\": \"lb\"\n }\n ]\n }\n ]\n }\n ]\n },\n \"code\": \"lightweight_parcel\"\n}"
response = http.request(request)
puts response.read_body{
"resource": {
"type": "ProductProfile",
"id": 27,
"name": "Lightweight Parcel",
"code": "lightweight_parcel",
"matched_count": 0,
"classification": {
"status": "queued",
"indexed_at": null
},
"created_at": "2026-08-04T10:30:00Z",
"updated_at": "2026-08-04T10:30:00Z"
}
}{
"errors": [
{
"type": "parameters",
"message": "The supplied parameters are invalid."
}
]
}{
"errors": [
{
"type": "unable_to_process",
"message": "Unknown condition field \"unknown_field\"."
}
]
}Create Product Profile
Creates a Product Profile. When code is omitted or blank, ShipStream generates one from
the name. Classification is scheduled after the save commits. Add
fields=conditions,conditions_readable to include canonical conditions in the created
resource.
curl --request POST \
--url https://{base_url_domain}/api/global/v1/inventory/product-profiles \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Lightweight Parcel",
"conditions": {
"or": [
{
"and": [
{
"<=": [
{
"var": "weight"
},
{
"value": 15,
"unit": "lb"
}
]
}
]
}
]
},
"code": "lightweight_parcel"
}
'import requests
url = "https://{base_url_domain}/api/global/v1/inventory/product-profiles"
payload = {
"name": "Lightweight Parcel",
"conditions": { "or": [{ "and": [{ "<=": [
{ "var": "weight" },
{
"value": 15,
"unit": "lb"
}
] }] }] },
"code": "lightweight_parcel"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Lightweight Parcel',
conditions: {or: [{and: [{'<=': [{var: 'weight'}, {value: 15, unit: 'lb'}]}]}]},
code: 'lightweight_parcel'
})
};
fetch('https://{base_url_domain}/api/global/v1/inventory/product-profiles', 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://{base_url_domain}/api/global/v1/inventory/product-profiles",
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([
'name' => 'Lightweight Parcel',
'conditions' => [
'or' => [
[
'and' => [
[
'<=' => [
[
'var' => 'weight'
],
[
'value' => 15,
'unit' => 'lb'
]
]
]
]
]
]
],
'code' => 'lightweight_parcel'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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://{base_url_domain}/api/global/v1/inventory/product-profiles"
payload := strings.NewReader("{\n \"name\": \"Lightweight Parcel\",\n \"conditions\": {\n \"or\": [\n {\n \"and\": [\n {\n \"<=\": [\n {\n \"var\": \"weight\"\n },\n {\n \"value\": 15,\n \"unit\": \"lb\"\n }\n ]\n }\n ]\n }\n ]\n },\n \"code\": \"lightweight_parcel\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://{base_url_domain}/api/global/v1/inventory/product-profiles")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Lightweight Parcel\",\n \"conditions\": {\n \"or\": [\n {\n \"and\": [\n {\n \"<=\": [\n {\n \"var\": \"weight\"\n },\n {\n \"value\": 15,\n \"unit\": \"lb\"\n }\n ]\n }\n ]\n }\n ]\n },\n \"code\": \"lightweight_parcel\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://{base_url_domain}/api/global/v1/inventory/product-profiles")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Lightweight Parcel\",\n \"conditions\": {\n \"or\": [\n {\n \"and\": [\n {\n \"<=\": [\n {\n \"var\": \"weight\"\n },\n {\n \"value\": 15,\n \"unit\": \"lb\"\n }\n ]\n }\n ]\n }\n ]\n },\n \"code\": \"lightweight_parcel\"\n}"
response = http.request(request)
puts response.read_body{
"resource": {
"type": "ProductProfile",
"id": 27,
"name": "Lightweight Parcel",
"code": "lightweight_parcel",
"matched_count": 0,
"classification": {
"status": "queued",
"indexed_at": null
},
"created_at": "2026-08-04T10:30:00Z",
"updated_at": "2026-08-04T10:30:00Z"
}
}{
"errors": [
{
"type": "parameters",
"message": "The supplied parameters are invalid."
}
]
}{
"errors": [
{
"type": "unable_to_process",
"message": "Unknown condition field \"unknown_field\"."
}
]
}Authorizations
Generate a JWT access token through a Custom Global Integration and provide it with each request in the Authorization header prefixed with "Bearer" and then a single space.
Query Parameters
Select fields of the ProductProfile object. See the
selecting fields page for more information.
Specify fields of the ProductProfile object to include in the response.
all, name, code, conditions, conditions_readable, matched_count, classification, created_at, updated_at Body
Human-readable Product Profile name.
1 - 255"Lightweight Parcel"
A one-level OR-of-AND condition tree. The server accepts the {"and": [...]} shorthand
for a single group and always returns the canonical {"or": [{"and": [...]}]} form.
OpenAPI validates the structural envelope. ShipStream remains authoritative for available
Product fields, field/operator compatibility, option values, measurement units, raw CEL
validity, normalization, the limit of 64 condition rows across all groups, and the
65,535-byte compiled-expression limit. Editor clients can
load the applicable Product field catalogue from
GET /api/global/v1/inventory/product-profiles/condition-fields or
GET /api/global/v1/inventory/handling-classes/condition-fields.
- Option 1
- Option 2
Show child attributes
Show child attributes
{
"or": [
{
"and": [
{
"<=": [
{ "var": "weight" },
{ "value": 15, "unit": "lb" }
]
}
]
}
]
}
Optional stable code; blank or omitted values are generated from the name.
64^[A-Za-z0-9_]*$"lightweight_parcel"
Response
Product Profile created and classification scheduled.
A reusable Product classification whose conditions may match many Products. Classification is
asynchronous: after a create or condition update, poll the resource until
classification.status is up_to_date. This status confirms that the Profile's current
conditions were classified. Product changes flow through a separate asynchronous changelog and
may not appear immediately in materialized membership.
Show child attributes
Show child attributes
{
"type": "ProductProfile",
"id": 26,
"name": "Lightweight Parcel",
"code": "lightweight_parcel",
"conditions": {
"or": [
{
"and": [
{
"<=": [
{ "var": "weight" },
{
"value": 15,
"unit": "lb",
"base_value": 15
}
]
}
]
}
]
},
"conditions_readable": "((present(weight) && weight <= 15.0))",
"matched_count": 482,
"classification": {
"status": "up_to_date",
"indexed_at": "2026-08-04T09:15:00Z"
},
"created_at": "2026-07-15T14:30:00Z",
"updated_at": "2026-08-04T09:15:00Z"
}
Was this page helpful?