curl --request GET \
--url https://api.hi-doctor.ai/v1/users/subscriptions/renewal-options/ \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.hi-doctor.ai/v1/users/subscriptions/renewal-options/"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.hi-doctor.ai/v1/users/subscriptions/renewal-options/', 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.hi-doctor.ai/v1/users/subscriptions/renewal-options/",
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.hi-doctor.ai/v1/users/subscriptions/renewal-options/"
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.hi-doctor.ai/v1/users/subscriptions/renewal-options/")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hi-doctor.ai/v1/users/subscriptions/renewal-options/")
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{
"category": "weight_loss",
"mode": "early_order",
"blocked_code": null,
"subscription": {
"id": "0a1b2c3d-4e5f-4a6b-8c9d-000000000006",
"status": "active",
"price_cents": 2500,
"currency": "EUR",
"started_at": "2026-05-25T08:00:00Z",
"current_period_start": "2026-07-27T08:00:00Z",
"current_period_end": "2026-08-24T08:00:00Z",
"cancel_at_period_end": false,
"canceled_at": null,
"treatment_id": "wegovy",
"category": "weight_loss",
"interval": "week",
"interval_count": 4,
"cycle_days": 28,
"payment_method_brand": null,
"payment_method_last4": null,
"early_order_locked_until": null,
"early_order_locked": false
},
"pending_consultation_id": null,
"current": {
"treatment_id": "wegovy",
"dosage": "0.5 mg",
"source": "subscription"
},
"ladder": {
"dosages": [
"0.25 mg",
"0.5 mg",
"1 mg",
"1.7 mg",
"2.4 mg"
],
"current": "0.5 mg",
"next": "1 mg",
"held_at_max": false
},
"alternatives": [],
"required_steps": [],
"review_steps": [],
"reusable_prefill": [],
"baseline_bmi": 31.4,
"baseline_unknown": false,
"plan": "subscription",
"price": {
"amount_cents": 2500,
"currency": "EUR",
"interval": "week",
"interval_count": 4,
"cycle_days": 28,
"plan": "subscription",
"supply_days": 28
},
"period": {
"current_period_end": "2026-08-24T08:00:00Z",
"early_order_locked_until": null
},
"express": null
}{
"code": "invalid_category"
}{
"detail": "Given token not valid for any token type",
"code": "token_not_valid",
"messages": [
{
"token_class": "AccessToken",
"token_type": "access",
"message": "Token is invalid"
}
]
}Get renewal options for a category
Tells the renewal UI what a patient may do for one treatment category. Requires the category query parameter and an authenticated patient.
mode is pending_choice (a renewal is awaiting the patient’s decision; pending_consultation_id identifies it), early_order (pull the renewal forward), express_reorder (rebook from past history) or blocked (with a blocked_code explaining why). The current treatment, dose ladder, price, and the steps the renewal screen must collect are returned for the patient’s client.
price is present whenever the patient has a prior treatment in the category: the live plan’s price, or otherwise the category’s default checkout price (the plan for weight loss and hair loss, the one-off elsewhere). It carries plan and supply_days so the client can say what the amount buys.
An unknown category is a 400 (invalid_category).
curl --request GET \
--url https://api.hi-doctor.ai/v1/users/subscriptions/renewal-options/ \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.hi-doctor.ai/v1/users/subscriptions/renewal-options/"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.hi-doctor.ai/v1/users/subscriptions/renewal-options/', 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.hi-doctor.ai/v1/users/subscriptions/renewal-options/",
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.hi-doctor.ai/v1/users/subscriptions/renewal-options/"
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.hi-doctor.ai/v1/users/subscriptions/renewal-options/")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hi-doctor.ai/v1/users/subscriptions/renewal-options/")
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{
"category": "weight_loss",
"mode": "early_order",
"blocked_code": null,
"subscription": {
"id": "0a1b2c3d-4e5f-4a6b-8c9d-000000000006",
"status": "active",
"price_cents": 2500,
"currency": "EUR",
"started_at": "2026-05-25T08:00:00Z",
"current_period_start": "2026-07-27T08:00:00Z",
"current_period_end": "2026-08-24T08:00:00Z",
"cancel_at_period_end": false,
"canceled_at": null,
"treatment_id": "wegovy",
"category": "weight_loss",
"interval": "week",
"interval_count": 4,
"cycle_days": 28,
"payment_method_brand": null,
"payment_method_last4": null,
"early_order_locked_until": null,
"early_order_locked": false
},
"pending_consultation_id": null,
"current": {
"treatment_id": "wegovy",
"dosage": "0.5 mg",
"source": "subscription"
},
"ladder": {
"dosages": [
"0.25 mg",
"0.5 mg",
"1 mg",
"1.7 mg",
"2.4 mg"
],
"current": "0.5 mg",
"next": "1 mg",
"held_at_max": false
},
"alternatives": [],
"required_steps": [],
"review_steps": [],
"reusable_prefill": [],
"baseline_bmi": 31.4,
"baseline_unknown": false,
"plan": "subscription",
"price": {
"amount_cents": 2500,
"currency": "EUR",
"interval": "week",
"interval_count": 4,
"cycle_days": 28,
"plan": "subscription",
"supply_days": 28
},
"period": {
"current_period_end": "2026-08-24T08:00:00Z",
"early_order_locked_until": null
},
"express": null
}{
"code": "invalid_category"
}{
"detail": "Given token not valid for any token type",
"code": "token_not_valid",
"messages": [
{
"token_class": "AccessToken",
"token_type": "access",
"message": "Token is invalid"
}
]
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Query Parameters
Response
pending_choice, early_order, express_reorder, blocked early_order_subscription_ending, early_order_period_unavailable, early_order_period_already_advanced, early_order_pending_review, no_prior_treatment, subscription_payment_required Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
subscription, one_off What the next order costs. plan says whether the amount is the category's subscription or its one-off consultation; supply_days is how many days of treatment that amount covers — 30 for a one-off hair-loss consultation, 28 for a one-off weight-loss one, the billing cycle on a plan.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes