catalog

GET /v1/catalog/plans

List the sellable plans with their prices.

Todos los endpoints de catalog

Autenticación

Este endpoint es público. No requiere credenciales ni organización; es lo que leen nuestro propio sitio de marketing y los motores de respuesta de IA.

Este endpoint no requiere ningún id de organización. Su clave ya identifica la organización a la que pertenece, y la respuesta está delimitada a ella.

Pruébalo

Reemplaza cualquier elemento entre corchetes angulares por tus propios valores, y el marcador de posición key con una clave de tu panel de control.

curl -X GET https://api.zinndigital.com/v1/catalog/plans

¿Has iniciado sesión? La consola de la API en tu panel de control rellena el ID de tu organización real y tu propia clave, y ejecuta la solicitud contra la API en vivo para que puedas ver la respuesta real. Abre este endpoint en la consola de la API

Detalles

Returns every active plan with its current version's **resolved entitlements** (product-line defaults overlaid with the plan's own) and its list prices, in the stored currency and interval. Prices are integer minor units + an ISO currency code (CLAUDE.md §2.8); USD is the base, and a derived, charm-rounded row is served for every enabled currency once the FX refresh has run (docs/29 §2). **Public** (docs/35 #19). **`prices` is a multi-row array, one entry per (interval, currency)** — never a single pre-converted row. A client selects the entry matching the customer's chosen currency AND interval, and must render **nothing** rather than fall back to an amount in a different currency: a number in the wrong currency, or the right number under the wrong symbol, is worse than an absent price (#471). **Each plan carries `plan_version_id`, the identifier that makes it purchasable.** A `hosting_plan` cart line pins a plan *version*, not a plan, so before this field existed a customer could browse the catalogue and had no way to buy anything in it (#463). The full self-serve path is `POST /v1/carts` → `POST /v1/carts/{cartId}/lines` with `{kind: hosting_plan, plan_version_id, metadata: {interval}}` → `POST /v1/carts/{cartId}/checkout`. An **internal** plan is never listed here and the cart refuses it, so the unlimited staff plan cannot be self-served. Returned **whole, not cursor-paginated** — a deliberate, documented deviation matching `getTranslationBundle`: the catalogue is our own bounded content, and a pricing page or the pricing slider needs every tier at once, not 50 at a time. The response is bounded by a hard server-side cap; a catalogue that would exceed it is a `422` (it never silently truncates), which cannot happen with today's catalogue and exists only so unbounded future growth fails loudly. Cacheable exactly like `listProductLines` (strong `ETag` + `max-age=60`).

Parámetros

NombreTipoObligatorio¿Qué es esto?
product_line (query)stringNoRestrict to one product line by its code (e.g. `footprint_free`). Unknown code → empty list.
currency (query)stringNoNarrow each plan's `prices` array to a single ISO 4217 currency. **Optional and additive**: omitting it returns every currency exactly as before, so no existing client changes b…
If-None-Match (header)stringNoA previously returned `ETag`; a match responds `304`.

Respuesta

NombreTipoObligatorio¿Qué es esto?
dataCatalogPlan[]

Errores que este endpoint puede devolver

422 · 429