curl --request GET \
--url https://api.cope.com/v1/commerce/subscriptions/{id}/changes \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.cope.com/v1/commerce/subscriptions/{id}/changes"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.cope.com/v1/commerce/subscriptions/{id}/changes', 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.cope.com/v1/commerce/subscriptions/{id}/changes",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.cope.com/v1/commerce/subscriptions/{id}/changes"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.cope.com/v1/commerce/subscriptions/{id}/changes")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.cope.com/v1/commerce/subscriptions/{id}/changes")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": [
{
"effective_at": "<string>",
"effective_confirmed_at": "<string>",
"failure": {
"code": "<string>",
"message": "<string>"
},
"from": {
"amount_cents": 123,
"currency": "<string>",
"plan_id": "<string>"
},
"reason": "<string>",
"requested_by": {
"actor_id": "<string>",
"actor_type": "<string>",
"business_id": "<string>",
"initiated_by": "<string>"
},
"status": "processing",
"subscription_id": "<string>",
"to": {
"amount_cents": 123,
"currency": "<string>",
"plan_id": "<string>"
},
"type": "price"
}
],
"pagination": {
"current_page": 123,
"per_page": 123,
"total_count": 123,
"total_pages": 123
}
}{
"code": "invalid_request",
"detail": "The request could not be parsed. Check the query string and the request body.",
"request_id": "req_123",
"status": 400,
"title": "Invalid Request",
"type": "https://docs.cope.com/errors/invalid_request"
}{
"code": "<string>",
"request_id": "<string>",
"status": 123,
"title": "<string>",
"type": "<string>",
"detail": "<string>",
"errors": [
{
"code": "<string>",
"detail": "<string>",
"param": "<string>"
}
]
}{
"code": "<string>",
"request_id": "<string>",
"status": 123,
"title": "<string>",
"type": "<string>",
"detail": "<string>",
"errors": [
{
"code": "<string>",
"detail": "<string>",
"param": "<string>"
}
]
}{
"code": "<string>",
"request_id": "<string>",
"status": 123,
"title": "<string>",
"type": "<string>",
"detail": "<string>",
"errors": [
{
"code": "<string>",
"detail": "<string>",
"param": "<string>"
}
]
}List a subscription's price and plan change attempts
Every attempt to change this subscription’s recurring amount (price) or to move it to
another plan (plan), newest first, whether it was applied or refused. A refused attempt
is recorded too and reads status: failed with a failure saying what stopped it, so an
empty list means no amount or plan change has ever been attempted.
Pause, resume and cancel are not in this list, and not in latest_change either. They
are recorded separately, and each of those three operations returns its own record in its
own response. What they did to the subscription is on
GET /v1/commerce/subscriptions/{id}: status reads paused after a pause and
canceling after a cancel of either mode, paused_at is set for as long as the
subscription is paused and null once it is resumed, and cancel_at carries when the
cancellation takes effect.
curl --request GET \
--url https://api.cope.com/v1/commerce/subscriptions/{id}/changes \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.cope.com/v1/commerce/subscriptions/{id}/changes"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.cope.com/v1/commerce/subscriptions/{id}/changes', 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.cope.com/v1/commerce/subscriptions/{id}/changes",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.cope.com/v1/commerce/subscriptions/{id}/changes"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.cope.com/v1/commerce/subscriptions/{id}/changes")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.cope.com/v1/commerce/subscriptions/{id}/changes")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": [
{
"effective_at": "<string>",
"effective_confirmed_at": "<string>",
"failure": {
"code": "<string>",
"message": "<string>"
},
"from": {
"amount_cents": 123,
"currency": "<string>",
"plan_id": "<string>"
},
"reason": "<string>",
"requested_by": {
"actor_id": "<string>",
"actor_type": "<string>",
"business_id": "<string>",
"initiated_by": "<string>"
},
"status": "processing",
"subscription_id": "<string>",
"to": {
"amount_cents": 123,
"currency": "<string>",
"plan_id": "<string>"
},
"type": "price"
}
],
"pagination": {
"current_page": 123,
"per_page": 123,
"total_count": 123,
"total_pages": 123
}
}{
"code": "invalid_request",
"detail": "The request could not be parsed. Check the query string and the request body.",
"request_id": "req_123",
"status": 400,
"title": "Invalid Request",
"type": "https://docs.cope.com/errors/invalid_request"
}{
"code": "<string>",
"request_id": "<string>",
"status": 123,
"title": "<string>",
"type": "<string>",
"detail": "<string>",
"errors": [
{
"code": "<string>",
"detail": "<string>",
"param": "<string>"
}
]
}{
"code": "<string>",
"request_id": "<string>",
"status": 123,
"title": "<string>",
"type": "<string>",
"detail": "<string>",
"errors": [
{
"code": "<string>",
"detail": "<string>",
"param": "<string>"
}
]
}{
"code": "<string>",
"request_id": "<string>",
"status": 123,
"title": "<string>",
"type": "<string>",
"detail": "<string>",
"errors": [
{
"code": "<string>",
"detail": "<string>",
"param": "<string>"
}
]
}Authorizations
Bearer credential for the public API. Vendor integrations should send a live COPE API key (ck_live_*; keys issued earlier as cope_sk_live_* keep working). Clerk bearer tokens are also accepted when paired with X-Cope-Business-Id.
Path Parameters
id public identifier.
^sub_[A-Za-z0-9]{8,32}$"sub_A1b2C3d4E5f6G7h8"
Query Parameters
Page number for paginated results. Values below 1 and non-numeric values are ignored and the first page is returned; a page past the last one returns the last page.
x >= 1Number of records per page. Defaults to 12; values above 25 are clamped to 25; values below 1 and non-numeric values are ignored and the default is used.
1 <= x <= 25