Products API
PUT/api/v1/products/{id}
Product availabilityAlgaPSA

Update product

Updates a product catalog entry by UUID. Send prices to replace the current price window (prices[0] is primary and is mirrored into default_rate) and scheduled_prices to replace the future window; either is applied in full or rejected with 400. Sending only default_rate rewrites the rate of the primary current price. Shorthand: currency_code + default_rate (integer minor units) upserts that single currency as the primary price (prices[0], mirrored into default_rate), replacing its rate or adding it, and leaves the other current prices of the product untouched; default_rate is required with currency_code and currency_code cannot be combined with prices. A default_rate that differs from prices[0].rate, currency_code without default_rate, currency_code together with prices, an unsupported currency, a fractional or negative rate, or a duplicate currency returns 400.

RBAC · service

Path parameters

idstring <uuid>Required
Product UUID.

Request body

Content type: application/json

service_namestring
min length 1 · max length 255
custom_service_type_idstring <uuid>
billing_methodstring
default "usage"
Enum: usage
default_ratenumber
≥ 0
currency_codestring
Shorthand for one price: with default_rate it upserts a single prices entry { currency_code, rate: default_rate } (default_rate is integer minor units, same as prices[].rate) and never writes a catalog column. Must be from the supported currency list. default_rate is required with it. On create it creates that one price; on update it sets that currency as the primary price (prices[0], mirrored into default_rate), replaces its rate if present or adds it, and leaves the other current prices untouched. Cannot be combined with prices (400).
unit_of_measurestring
min length 1 · max length 128
unit_codestring
category_idanyOf
anyOf (option 1)string <uuid>
anyOf (option 2)null
anyOf (option 3)null
tax_rate_idanyOf
anyOf (option 1)string <uuid>
anyOf (option 2)null
anyOf (option 3)null
descriptionanyOf
anyOf (option 1)string
max length 2048
anyOf (option 2)null
anyOf (option 3)null
skuanyOf
anyOf (option 1)string
max length 128
anyOf (option 2)null
anyOf (option 3)null
barcodeanyOf
anyOf (option 1)string
max length 255
anyOf (option 2)null
anyOf (option 3)null
costanyOf
anyOf (option 1)number
≥ 0
anyOf (option 2)null
anyOf (option 3)null
cost_currencyanyOf
anyOf (option 1)string
min length 3 · max length 3
anyOf (option 2)null
anyOf (option 3)null
vendoranyOf
anyOf (option 1)string
max length 255
anyOf (option 2)null
anyOf (option 3)null
manufactureranyOf
anyOf (option 1)string
max length 255
anyOf (option 2)null
anyOf (option 3)null
product_categoryanyOf
anyOf (option 1)string
max length 255
anyOf (option 2)null
anyOf (option 3)null
is_licenseboolean
default false
license_termanyOf
anyOf (option 1)string
max length 64
anyOf (option 2)null
anyOf (option 3)null
license_billing_cadenceanyOf
anyOf (option 1)string
max length 64
anyOf (option 2)null
anyOf (option 3)null
is_activeboolean
default true
pricesarray of object
Full set of current prices, rate in integer minor units (e.g. cents), currency_code from the supported currency list. Replaces the entire current price window; omitted currencies are removed and prices: [] clears it. prices[0] is the primary price and is mirrored into default_rate. Currencies must be unique.
itemsobject
currency_codestringRequired
rateintegerRequired
≥ 0
effective_dateany
price_idany
service_idany
tenantany
created_atany
updated_atany
display_orderany
scheduled_pricesarray of object
Full set of future-dated prices (each effective_date must be after today). Replaces the entire future price window; scheduled_prices: [] clears it. Does not change the current prices or default_rate.
itemsobject
currency_codestringRequired
rateintegerRequired
≥ 0
effective_dateany
price_idany
service_idany
tenantany
created_atany
updated_atany
display_orderany

Response body

Success response 200 · schema ProductEnvelope

dataobjectRequired
Product catalog entry.
service_idstring <uuid>Required
tenantstring <uuid>Required
service_namestringRequired
custom_service_type_idstring <uuid>Required
billing_methodstringRequired
Enum: usage
default_ratenumberRequired
unit_of_measurestringRequired
unit_codestringNullable
category_idstring <uuid>Nullable
tax_rate_idstring <uuid>Nullable
descriptionstringNullable
item_kindstringRequired
Enum: product
is_activeboolean
skustringNullable
barcodestringNullable
costnumberNullable
cost_currencystringNullable
min length 3 · max length 3
vendorstringNullable
manufacturerstringNullable
product_categorystringNullable
is_licenseboolean
license_termstringNullable
license_billing_cadencestringNullable
service_type_namestring
pricesarray of ProductPrice
Current price per currency (latest effective on or before today).
itemsobject
currency_codestringRequired
min length 3 · max length 3
ratenumberRequired
Rate in integer minor units (e.g. cents).
display_orderinteger
Position within its window; 0 is the primary price. Responses are sorted by display_order, then currency_code.
effective_datestringNullable
Calendar date the price takes effect; the epoch when untagged.
scheduled_pricesarray of ProductPrice
Future-dated prices that are not yet billed.
itemsobject
currency_codestringRequired
min length 3 · max length 3
ratenumberRequired
Rate in integer minor units (e.g. cents).
display_orderinteger
Position within its window; 0 is the primary price. Responses are sorted by display_order, then currency_code.
effective_datestringNullable
Calendar date the price takes effect; the epoch when untagged.
metaobject

Response codes

200
Product updated successfully.
400
Validation error, including rejected price writes: unsupported currency, fractional or negative rate, duplicate currency, scheduled date not in the future, default_rate conflicting with prices[0].rate, an unsupported currency_code, currency_code without default_rate, or currency_code combined with prices.
401
Authentication failed.
403
Authenticated user lacks the required permission.
404
Product not found.
409
A product with the submitted SKU or barcode already exists.