curl --request PATCH \
--url https://{clinic}.{region}.practicehub.io/v3/api/billable_items/{id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"description": "<string>",
"amount": "45.00",
"tax_id": 123,
"modality_id": 123,
"sku": "<string>",
"stock_alert_level": 1,
"active": true,
"metadata": {}
}
'import requests
url = "https://{clinic}.{region}.practicehub.io/v3/api/billable_items/{id}"
payload = {
"description": "<string>",
"amount": "45.00",
"tax_id": 123,
"modality_id": 123,
"sku": "<string>",
"stock_alert_level": 1,
"active": True,
"metadata": {}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
description: '<string>',
amount: '45.00',
tax_id: 123,
modality_id: 123,
sku: '<string>',
stock_alert_level: 1,
active: true,
metadata: {}
})
};
fetch('https://{clinic}.{region}.practicehub.io/v3/api/billable_items/{id}', 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://{clinic}.{region}.practicehub.io/v3/api/billable_items/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'description' => '<string>',
'amount' => '45.00',
'tax_id' => 123,
'modality_id' => 123,
'sku' => '<string>',
'stock_alert_level' => 1,
'active' => true,
'metadata' => [
]
]),
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://{clinic}.{region}.practicehub.io/v3/api/billable_items/{id}"
payload := strings.NewReader("{\n \"description\": \"<string>\",\n \"amount\": \"45.00\",\n \"tax_id\": 123,\n \"modality_id\": 123,\n \"sku\": \"<string>\",\n \"stock_alert_level\": 1,\n \"active\": true,\n \"metadata\": {}\n}")
req, _ := http.NewRequest("PATCH", 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.patch("https://{clinic}.{region}.practicehub.io/v3/api/billable_items/{id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"description\": \"<string>\",\n \"amount\": \"45.00\",\n \"tax_id\": 123,\n \"modality_id\": 123,\n \"sku\": \"<string>\",\n \"stock_alert_level\": 1,\n \"active\": true,\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://{clinic}.{region}.practicehub.io/v3/api/billable_items/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"description\": \"<string>\",\n \"amount\": \"45.00\",\n \"tax_id\": 123,\n \"modality_id\": 123,\n \"sku\": \"<string>\",\n \"stock_alert_level\": 1,\n \"active\": true,\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": 12,
"type": "service",
"description": "Initial consultation",
"sku": null,
"amount": "60.00",
"tax_id": null,
"taxable": false,
"modality_id": null,
"stock_alert_level": null,
"active": true,
"sort_order": 1,
"created_at": "2026-09-01T09:15:00Z"
}
}{
"message": "<string>",
"code": "<string>",
"errors": {}
}{
"message": "<string>",
"code": "<string>",
"errors": {}
}{
"message": "<string>",
"code": "<string>",
"errors": {}
}{
"message": "<string>",
"code": "<string>",
"errors": {}
}{
"message": "<string>",
"code": "<string>",
"errors": {}
}Update billable_items
curl --request PATCH \
--url https://{clinic}.{region}.practicehub.io/v3/api/billable_items/{id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"description": "<string>",
"amount": "45.00",
"tax_id": 123,
"modality_id": 123,
"sku": "<string>",
"stock_alert_level": 1,
"active": true,
"metadata": {}
}
'import requests
url = "https://{clinic}.{region}.practicehub.io/v3/api/billable_items/{id}"
payload = {
"description": "<string>",
"amount": "45.00",
"tax_id": 123,
"modality_id": 123,
"sku": "<string>",
"stock_alert_level": 1,
"active": True,
"metadata": {}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
description: '<string>',
amount: '45.00',
tax_id: 123,
modality_id: 123,
sku: '<string>',
stock_alert_level: 1,
active: true,
metadata: {}
})
};
fetch('https://{clinic}.{region}.practicehub.io/v3/api/billable_items/{id}', 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://{clinic}.{region}.practicehub.io/v3/api/billable_items/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'description' => '<string>',
'amount' => '45.00',
'tax_id' => 123,
'modality_id' => 123,
'sku' => '<string>',
'stock_alert_level' => 1,
'active' => true,
'metadata' => [
]
]),
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://{clinic}.{region}.practicehub.io/v3/api/billable_items/{id}"
payload := strings.NewReader("{\n \"description\": \"<string>\",\n \"amount\": \"45.00\",\n \"tax_id\": 123,\n \"modality_id\": 123,\n \"sku\": \"<string>\",\n \"stock_alert_level\": 1,\n \"active\": true,\n \"metadata\": {}\n}")
req, _ := http.NewRequest("PATCH", 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.patch("https://{clinic}.{region}.practicehub.io/v3/api/billable_items/{id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"description\": \"<string>\",\n \"amount\": \"45.00\",\n \"tax_id\": 123,\n \"modality_id\": 123,\n \"sku\": \"<string>\",\n \"stock_alert_level\": 1,\n \"active\": true,\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://{clinic}.{region}.practicehub.io/v3/api/billable_items/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"description\": \"<string>\",\n \"amount\": \"45.00\",\n \"tax_id\": 123,\n \"modality_id\": 123,\n \"sku\": \"<string>\",\n \"stock_alert_level\": 1,\n \"active\": true,\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": 12,
"type": "service",
"description": "Initial consultation",
"sku": null,
"amount": "60.00",
"tax_id": null,
"taxable": false,
"modality_id": null,
"stock_alert_level": null,
"active": true,
"sort_order": 1,
"created_at": "2026-09-01T09:15:00Z"
}
}{
"message": "<string>",
"code": "<string>",
"errors": {}
}{
"message": "<string>",
"code": "<string>",
"errors": {}
}{
"message": "<string>",
"code": "<string>",
"errors": {}
}{
"message": "<string>",
"code": "<string>",
"errors": {}
}{
"message": "<string>",
"code": "<string>",
"errors": {}
}Authorizations
API key from Developers → API Keys, sent as Authorization: Bearer .
Path Parameters
Body
The item's name as shown on invoices, up to 255 characters.
255service or product.
service, product Unit price in the account currency, two decimal places. Negative amounts are allowed (discounts).
^-?\d+(\.\d{1,2})?$"45.00"
Tax rate applied (taxes are managed in Settings › Billing); null for none.
Restrict the item to one practitioner modality; null for all.
Optional stock-keeping code.
255Products only: alert when stock falls to this level; null for no alert.
x >= 0Whether the item can still be billed. Deactivate instead of deleting; there is no DELETE.
Integrator-owned key/value metadata (max 50 keys). Values are strings (≤500 chars), numbers or booleans and read back with the type they were written with. On write, a null value removes the key. Filter with metadata[key]=op:value; number operands compare numerically.
Show child attributes
Show child attributes
Response
The resource
Show child attributes
Show child attributes
{
"id": 12,
"type": "service",
"description": "Initial consultation",
"sku": null,
"amount": "60.00",
"tax_id": null,
"taxable": false,
"modality_id": null,
"stock_alert_level": null,
"active": true,
"sort_order": 1,
"created_at": "2026-09-01T09:15:00Z"
}
Was this page helpful?