curl --request POST \
--url https://public-api.stora.co/2025-09/price_adjustments \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"subscription": {
"id": "sub_0c957d38b021758e"
},
"percentage": 10,
"effective_from": "2025-02-22",
"applies_to": {
"unit_types": true
}
}
'import requests
url = "https://public-api.stora.co/2025-09/price_adjustments"
payload = {
"subscription": { "id": "sub_0c957d38b021758e" },
"percentage": 10,
"effective_from": "2025-02-22",
"applies_to": { "unit_types": True }
}
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({
subscription: {id: 'sub_0c957d38b021758e'},
percentage: 10,
effective_from: '2025-02-22',
applies_to: {unit_types: true}
})
};
fetch('https://public-api.stora.co/2025-09/price_adjustments', 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://public-api.stora.co/2025-09/price_adjustments",
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([
'subscription' => [
'id' => 'sub_0c957d38b021758e'
],
'percentage' => 10,
'effective_from' => '2025-02-22',
'applies_to' => [
'unit_types' => true
]
]),
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://public-api.stora.co/2025-09/price_adjustments"
payload := strings.NewReader("{\n \"subscription\": {\n \"id\": \"sub_0c957d38b021758e\"\n },\n \"percentage\": 10,\n \"effective_from\": \"2025-02-22\",\n \"applies_to\": {\n \"unit_types\": true\n }\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://public-api.stora.co/2025-09/price_adjustments")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"subscription\": {\n \"id\": \"sub_0c957d38b021758e\"\n },\n \"percentage\": 10,\n \"effective_from\": \"2025-02-22\",\n \"applies_to\": {\n \"unit_types\": true\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://public-api.stora.co/2025-09/price_adjustments")
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 \"subscription\": {\n \"id\": \"sub_0c957d38b021758e\"\n },\n \"percentage\": 10,\n \"effective_from\": \"2025-02-22\",\n \"applies_to\": {\n \"unit_types\": true\n }\n}"
response = http.request(request)
puts response.read_body{
"price_adjustment": {
"id": "pradj_295h6kfm9ro15lo",
"adjust_on": "2025-03-14",
"adjustment": null,
"applies_to": {
"products": false,
"protection_levels": false,
"unit_types": true
},
"created_at": "2025-02-22T14:41:00Z",
"estimation": {
"post_amount": {
"amount": 47666,
"currency": "GBP",
"formatted": "£476.66"
},
"pre_amount": {
"amount": 43333,
"currency": "GBP",
"formatted": "£433.33"
}
},
"invoice": null,
"notification": {
"notice_period": "send_immediately",
"scheduled_at": "2025-02-22",
"sent_at": null
},
"percentage": 10,
"status": "draft",
"subscription": {
"id": "sub_0c957d38b021758e"
},
"updated_at": "2025-02-22T14:41:00Z"
},
"meta": {
"request_id": "01563646-58c1-4607-8fe0-cae3e92c4477",
"curies": [
{
"name": "bo",
"href": "https://app.stora.test{rel}",
"templated": true,
"title": "Backoffice"
},
{
"name": "sf",
"href": "https://acme.stora.test{rel}",
"templated": true,
"title": "Storefront"
}
]
}
}{
"error": {
"code": "forbidden",
"details": [],
"links": [
{
"kind": "open_api",
"name": "OpenAPI specification",
"url": "https://docs.stora.test/2025-09/openapi.json"
},
{
"kind": "documentation",
"name": "Errors",
"url": "https://docs.stora.test/2025-09/guides/errors"
}
],
"message": "Used API token does not have the required scope. Access to this resource requires scope \"public.price_adjustment:skip_notifications\".",
"request_id": "01563646-58c1-4607-8fe0-cae3e92c4477",
"type": "invalid_request_error"
}
}{
"error": {
"code": "duplicate_price_adjustment",
"details": [],
"links": [
{
"kind": "open_api",
"name": "OpenAPI specification",
"url": "https://docs.stora.test/2025-09/openapi.json"
},
{
"kind": "documentation",
"name": "Errors",
"url": "https://docs.stora.test/2025-09/guides/errors"
}
],
"message": "A price adjustment is already scheduled for this subscription on 2025-03-14.",
"request_id": "01563646-58c1-4607-8fe0-cae3e92c4477",
"type": "invalid_request_error"
}
}{
"error": {
"code": "invalid_content",
"details": [
{
"message": "object at root is missing required properties: subscription, percentage, effective_from",
"pointer": null
}
],
"links": [
{
"kind": "open_api",
"name": "OpenAPI specification",
"url": "https://docs.stora.test/2025-09/openapi.json"
},
{
"kind": "documentation",
"name": "Errors",
"url": "https://docs.stora.test/2025-09/guides/errors"
}
],
"message": "The request body content is not valid.",
"request_id": "01563646-58c1-4607-8fe0-cae3e92c4477",
"type": "invalid_request_error"
}
}Create a Price Adjustment
Create a new price adjustment for a subscription.
The adjustment date is resolved from effective_from to the subscription’s first renewal date on or
after it, and returned as adjust_on. The price adjustment lands as a draft unless schedule is
true, in which case it is scheduled (pending) immediately.
When the notification object is omitted, the operator’s default notice period applies. If that
default does not fit before the resolved adjust_on, notification.notice_period reads back as
send_immediately. An operator whose default is no notice at all resolves to no notification, which
requires the public.price_adjustment:skip_notifications scope just as an explicit null does.
Notifications are only sent for scheduled (pending) adjustments: a
send_immediately notice is delivered as soon as the adjustment is scheduled, so a draft reads
back notification.sent_at as null until it is scheduled. A notice_period of null skips
customer notification through Stora and requires the public.price_adjustment:skip_notifications scope.
A subscription can hold only one scheduled price adjustment at a time. Scheduling a second one is a
409; delete the existing adjustment
before scheduling a replacement. The restriction lifts once the existing adjustment has been applied,
so the next one can be scheduled while the previous is still awaiting its invoice.
A 409 is also returned when the request conflicts with the subscription’s current state: the
subscription has not been billed through Stripe (stripe_subscription_id is null), is not active, is
archived, or is scheduled to end; the subscription has no future renewal dates to adjust on; or a
scheduled adjustment already exists for that subscription on the resolved adjust_on. Neither check
applies to drafts, so a draft can always be created alongside a scheduled adjustment.
Required authorization scope: public.price_adjustment:write
curl --request POST \
--url https://public-api.stora.co/2025-09/price_adjustments \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"subscription": {
"id": "sub_0c957d38b021758e"
},
"percentage": 10,
"effective_from": "2025-02-22",
"applies_to": {
"unit_types": true
}
}
'import requests
url = "https://public-api.stora.co/2025-09/price_adjustments"
payload = {
"subscription": { "id": "sub_0c957d38b021758e" },
"percentage": 10,
"effective_from": "2025-02-22",
"applies_to": { "unit_types": True }
}
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({
subscription: {id: 'sub_0c957d38b021758e'},
percentage: 10,
effective_from: '2025-02-22',
applies_to: {unit_types: true}
})
};
fetch('https://public-api.stora.co/2025-09/price_adjustments', 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://public-api.stora.co/2025-09/price_adjustments",
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([
'subscription' => [
'id' => 'sub_0c957d38b021758e'
],
'percentage' => 10,
'effective_from' => '2025-02-22',
'applies_to' => [
'unit_types' => true
]
]),
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://public-api.stora.co/2025-09/price_adjustments"
payload := strings.NewReader("{\n \"subscription\": {\n \"id\": \"sub_0c957d38b021758e\"\n },\n \"percentage\": 10,\n \"effective_from\": \"2025-02-22\",\n \"applies_to\": {\n \"unit_types\": true\n }\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://public-api.stora.co/2025-09/price_adjustments")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"subscription\": {\n \"id\": \"sub_0c957d38b021758e\"\n },\n \"percentage\": 10,\n \"effective_from\": \"2025-02-22\",\n \"applies_to\": {\n \"unit_types\": true\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://public-api.stora.co/2025-09/price_adjustments")
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 \"subscription\": {\n \"id\": \"sub_0c957d38b021758e\"\n },\n \"percentage\": 10,\n \"effective_from\": \"2025-02-22\",\n \"applies_to\": {\n \"unit_types\": true\n }\n}"
response = http.request(request)
puts response.read_body{
"price_adjustment": {
"id": "pradj_295h6kfm9ro15lo",
"adjust_on": "2025-03-14",
"adjustment": null,
"applies_to": {
"products": false,
"protection_levels": false,
"unit_types": true
},
"created_at": "2025-02-22T14:41:00Z",
"estimation": {
"post_amount": {
"amount": 47666,
"currency": "GBP",
"formatted": "£476.66"
},
"pre_amount": {
"amount": 43333,
"currency": "GBP",
"formatted": "£433.33"
}
},
"invoice": null,
"notification": {
"notice_period": "send_immediately",
"scheduled_at": "2025-02-22",
"sent_at": null
},
"percentage": 10,
"status": "draft",
"subscription": {
"id": "sub_0c957d38b021758e"
},
"updated_at": "2025-02-22T14:41:00Z"
},
"meta": {
"request_id": "01563646-58c1-4607-8fe0-cae3e92c4477",
"curies": [
{
"name": "bo",
"href": "https://app.stora.test{rel}",
"templated": true,
"title": "Backoffice"
},
{
"name": "sf",
"href": "https://acme.stora.test{rel}",
"templated": true,
"title": "Storefront"
}
]
}
}{
"error": {
"code": "forbidden",
"details": [],
"links": [
{
"kind": "open_api",
"name": "OpenAPI specification",
"url": "https://docs.stora.test/2025-09/openapi.json"
},
{
"kind": "documentation",
"name": "Errors",
"url": "https://docs.stora.test/2025-09/guides/errors"
}
],
"message": "Used API token does not have the required scope. Access to this resource requires scope \"public.price_adjustment:skip_notifications\".",
"request_id": "01563646-58c1-4607-8fe0-cae3e92c4477",
"type": "invalid_request_error"
}
}{
"error": {
"code": "duplicate_price_adjustment",
"details": [],
"links": [
{
"kind": "open_api",
"name": "OpenAPI specification",
"url": "https://docs.stora.test/2025-09/openapi.json"
},
{
"kind": "documentation",
"name": "Errors",
"url": "https://docs.stora.test/2025-09/guides/errors"
}
],
"message": "A price adjustment is already scheduled for this subscription on 2025-03-14.",
"request_id": "01563646-58c1-4607-8fe0-cae3e92c4477",
"type": "invalid_request_error"
}
}{
"error": {
"code": "invalid_content",
"details": [
{
"message": "object at root is missing required properties: subscription, percentage, effective_from",
"pointer": null
}
],
"links": [
{
"kind": "open_api",
"name": "OpenAPI specification",
"url": "https://docs.stora.test/2025-09/openapi.json"
},
{
"kind": "documentation",
"name": "Errors",
"url": "https://docs.stora.test/2025-09/guides/errors"
}
],
"message": "The request body content is not valid.",
"request_id": "01563646-58c1-4607-8fe0-cae3e92c4477",
"type": "invalid_request_error"
}
}Authorizations
Bearer Token necessary to use API
Body
Create Price Adjustment Request
Show child attributes
Show child attributes
Percentage change applied to the subscription's prices. Negative values are a decrease. Must be non-zero and greater than -100.
Date to resolve the adjustment date from. The adjustment fires on the first renewal date on or after this date. A calendar date in the operator's timezone. Use next_billing_period for the next renewal date.
When true, the price adjustment is scheduled (pending) immediately. When false, it lands as a draft.
Which of the subscription's line item kinds the adjustment applies to. Each option defaults to false. At least one must be true to schedule the adjustment.
Show child attributes
Show child attributes
How the customer is notified of the price adjustment before it is applied. When omitted, the operator's default notice period applies.
- Option 1
- Option 2
- Option 3
Show child attributes
Show child attributes
Was this page helpful?