Publish a product group from test to production environment. Uses UPSERT behavior — you can re-publish after making changes, unlike product publishing which only supports the first publish.
POST /v1/actions/subscription-product-group/publish-group
Authentication: API Key
Do not include the X-Environment header for this endpoint. Publishing is always one-way from test to production.
Request Body
Field Type Required Description idstring Yes Group ID (UUID format, must be a test environment group)
Example Request
SDK
TypeScript (fetch)
Java
Python
Go
Rust
C
C++
cURL
wget
await client . subscriptionProductGroups . publish ({
id: "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a" ,
});
// Uses callApi() helper from authentication.mdx
const result = await callApi ( "POST" , "/v1/actions/subscription-product-group/publish-group" , {
id: "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a" ,
});
console . log ( result . data );
// Uses callApi() helper from authentication.mdx
String body = """
{"id":"d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a"}""" ;
String response = callApi ( "POST" , "/v1/actions/subscription-product-group/publish-group" , body);
System . out . println (response);
# Uses call_api() helper from authentication.mdx
result = call_api( "POST" , "/v1/actions/subscription-product-group/publish-group" , {
"id" : "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a" ,
})
print (result[ "data" ])
// Uses callAPI() helper from authentication.mdx
body := map [ string ] interface {}{
"id" : "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a" ,
}
result , err := callAPI ( "POST" , "/v1/actions/subscription-product-group/publish-group" , body )
if err != nil {
log . Fatal ( err )
}
fmt . Println ( string ( result ))
// Uses call_api() helper from authentication.mdx
let body = serde_json :: json! ({
"id" : "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a"
});
let result = call_api ( "POST" , "/v1/actions/subscription-product-group/publish-group" , & body ) . await ? ;
println! ( "{}" , result );
/* Uses call_api() helper from authentication.mdx */
const char * body = "{ \" id \" : \" d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a \" }" ;
char * response = call_api ( "POST" , "/v1/actions/subscription-product-group/publish-group" , body);
printf ( " %s \n " , response);
free (response);
// Uses callApi() helper from authentication.mdx
std ::string body = R"({"id":"d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a"})" ;
std ::string response = callApi ( "POST" , "/v1/actions/subscription-product-group/publish-group" , body);
std ::cout << response << std ::endl;
MERCHANT_ID = "MER_2aUyqjCzEIiEcYMKj7TZtw"
TIMESTAMP = $( date +%s )
BODY = '{"id":"d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a"}'
BODY_HASH = $( echo -n " $BODY " | openssl dgst -sha256 -binary | base64 -w 0 )
CANONICAL_REQUEST = "POST
/v1/actions/subscription-product-group/publish-group
$TIMESTAMP
$BODY_HASH "
SIGNATURE = $( echo -n " $CANONICAL_REQUEST " | openssl dgst -sha256 -sign private_key.pem | base64 -w 0 )
curl -X POST "https://api.waffo.ai/v1/actions/subscription-product-group/publish-group" \
-H "Content-Type: application/json" \
-H "X-Merchant-Id: $MERCHANT_ID " \
-H "X-Timestamp: $TIMESTAMP " \
-H "X-Signature: $SIGNATURE " \
-d " $BODY "
MERCHANT_ID = "MER_2aUyqjCzEIiEcYMKj7TZtw"
TIMESTAMP = $( date +%s )
BODY = '{"id":"d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a"}'
BODY_HASH = $( echo -n " $BODY " | openssl dgst -sha256 -binary | base64 -w 0 )
CANONICAL_REQUEST = "POST
/v1/actions/subscription-product-group/publish-group
$TIMESTAMP
$BODY_HASH "
SIGNATURE = $( echo -n " $CANONICAL_REQUEST " | openssl dgst -sha256 -sign private_key.pem | base64 -w 0 )
wget -qO- "https://api.waffo.ai/v1/actions/subscription-product-group/publish-group" \
--header= "Content-Type: application/json" \
--header= "X-Merchant-Id: $MERCHANT_ID " \
--header= "X-Timestamp: $TIMESTAMP " \
--header= "X-Signature: $SIGNATURE " \
--post-data= " $BODY "
Unlike product publishing, group publishing supports repeated UPSERT operations . You can update a test group and re-publish it to production at any time. The production group will be created or updated to match the current test group.
Errors
Retry policy: Never retry 4xx — fix the request and resubmit. Retry 5xx with exponential backoff (start 5s, max 3 attempts).
Status errors[0].messageWhat it means Recommended handling 400 Missing required field: idRequest body did not include id Add id, resubmit 400 Can only publish test environment groupsThe supplied group is already in production (or otherwise not test) Only test-environment groups are publishable 400 Cannot publish: product_ids is emptyThe group has no member products Add at least one product via update-group, resubmit 404 Group not foundNo group exists for the supplied id Verify the id belongs to your store 500 Internal server errorInternal error or transient downstream failure Retry with exponential backoff (start 5s, max 3 attempts)