---
title: "Publish a new credit price-list version (admin only)"
method: POST
path: "/v1/admin/credit-prices"
---

# Publish a new credit price-list version (admin only)

`POST /v1/admin/credit-prices`

## Request

- Base URL: `https://api.clichefactory.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.clichefactory.com/v1/admin/credit-prices`
- Auth: none declared

Publish a new price-list version, atomic across every currency.

The sticky pricing rate is deliberately a human action. Nobody prices a
SaaS product at spot — we would end up with EUR 18.37 price points that
move weekly. A spot move raises an alert; a person decides.

`entries` is the complete set for the new version, not a patch: omitting a
currency retires it. Publishing per currency is what lets two currencies
drift apart across a repricing announcement, so it is not offered.

Versions are published, never mutated, so an old grant still points at the
exact price set that priced it.

## Headers

- `X-API-KEY` string, nullable

## Request body

- PublishPriceListRequest: Publish a new price-list version, atomic across every currency. The sticky pricing rate is a human decision: never derived from a live feed, and a spot move does not reprice anything on its own — it raises an alert a person acts on. ``entries`` is the **complete** set for the new version. Every currency we intend to keep selling in must appear; omitting one retires it. That is deliberately not something that can happen one row at a time, because per-currency publishes are what let two currencies drift apart across a repricing announcement.
  - `entries` CreditPriceEntryItem[], required
    - `currency` string, required
    - `credits_per_unit` integer, required
    - `min_topup_minor` integer
    - `pricing_fx_rate` number, nullable
  - `change_reason` 'launch' | 'repricing' | 'fx_review'
  - `announced_at` string, date-time, nullable: When customers were told. Required for a repricing.
  - `note` string, nullable

## Response `200`

Successful Response

- CreditPriceListResponse: The price-list version currently in force, with all its entries. Django renders checkout from this and quotes ``price_list_id`` back on the webhook so the server can reject a quote made against a superseded version. The entries are also the currency allow-list: a currency absent here cannot be sold in, and adding one is a data change rather than a deploy.
  - `price_list_id` integer, required
  - `effective_from` string, date-time, required
  - `change_reason` string
  - `announced_at` string, date-time, nullable
  - `entries` CreditPriceEntryItem[]
    - `currency` string, required
    - `credits_per_unit` integer, required
    - `min_topup_minor` integer
    - `pricing_fx_rate` number, nullable
  - `functional_currency` string
  - `created_by` string, nullable
  - `note` string, nullable

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/clichefactory/apis/aio-server.md) · [All operations](https://skmtc.dev/clichefactory/apis/aio-server/llms.txt) · [OpenAPI document](https://skmtc.dev/clichefactory/apis/aio-server/revisions/9bd59f9bbb31?raw)
