> ## Documentation Index
> Fetch the complete documentation index at: https://docs.chataigne.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Manage discounts

> Create location discounts, organization templates, and per-location product mappings.

Discounts are managed at one of two scopes:

* A **location discount** belongs to one restaurant.
* An **organization discount** is a template assigned to one or more locations.

A location list returns both kinds so you can inspect the offers that are effective for that restaurant. Organization-managed entries are read-only on location mutation endpoints; update their template or location mapping through the organization routes.

## Endpoints

```text Location discounts theme={null}
GET    /v1/locations/{location_id}/discounts
POST   /v1/locations/{location_id}/discounts
GET    /v1/locations/{location_id}/discounts/{discount_id}
PATCH  /v1/locations/{location_id}/discounts/{discount_id}
```

```text Organization templates theme={null}
GET    /v1/organizations/{organization_id}/discounts
POST   /v1/organizations/{organization_id}/discounts
GET    /v1/organizations/{organization_id}/discounts/{discount_id}
PATCH  /v1/organizations/{organization_id}/discounts/{discount_id}
```

```text Organization location mappings theme={null}
GET    /v1/organizations/{organization_id}/discounts/{discount_id}/locations
PUT    /v1/organizations/{organization_id}/discounts/{discount_id}/locations/{location_id}
```

Writes require `discounts.write`; reads require `discounts.read`. Organization API keys may act on child locations. A location-scoped key cannot act on organization routes.

## Create a location discount

Use public product and bundle IDs from the location's active Catalog API resource. Chataigne never accepts or returns private SKU or database IDs here.

```bash theme={null}
curl https://server.chataigne.ai/v1/locations/loc_123/discounts \
  -X POST \
  -H 'x-api-key: ck_live_...' \
  -H 'content-type: application/json' \
  -H 'idempotency-key: 86fa9212-87e5-4de8-951a-c119b26bb9b8' \
  -d '{
    "name": "Welcome 10%",
    "code": "WELCOME10",
    "visibility": "public",
    "once_per_customer": true,
    "combinable": true,
    "starts_on": "2026-09-01",
    "ends_on": "2026-09-30",
    "minimum_order": { "amount": 20, "currency": "EUR" },
    "required_items": [{ "type": "product", "id": "burger-classic" }],
    "benefit": { "type": "percentage", "percentage": 10 }
  }'
```

Date boundaries are inclusive calendar dates evaluated in the location timezone. `minimum_order.amount` uses whole major currency units; fixed discount amounts support two decimals. `PATCH` uses merge semantics: omitted fields stay unchanged; explicit `null` clears nullable fields such as `description`, `image_url`, dates, and `minimum_order`.

The benefit type is immutable. To change from a percentage to a free product, create a new discount and deactivate the old one with `PATCH { "enabled": false }`.

## Benefit types

| Type              | Required fields                                                           |
| ----------------- | ------------------------------------------------------------------------- |
| `percentage`      | `percentage` from more than 0 through 100                                 |
| `fixed_amount`    | `amount` with the target location currency                                |
| `free_product`    | exactly one product in `reward_items`                                     |
| `buy_one_get_one` | one or more product or bundle `reward_items`                              |
| `buy_x_get_y`     | positive `buy_quantity`, `free_quantity`, and product-only `reward_items` |
| `free_delivery`   | no additional field                                                       |

`required_items` are eligibility conditions; they do not limit a percentage or fixed amount to those line items.

## Organization mappings

Product IDs may differ between restaurant catalogs. Product-based organization discounts therefore carry reward and eligibility item mappings on each location assignment.

```bash theme={null}
curl https://server.chataigne.ai/v1/organizations/org_123/discounts/disc_456/locations/loc_123 \
  -X PUT \
  -H 'x-api-key: ck_live_...' \
  -H 'content-type: application/json' \
  -d '{
    "required_items": [{ "type": "product", "id": "burger-classic" }],
    "reward_items": [{ "type": "product", "id": "drink-cola" }]
  }'
```

`PUT` replaces both mapping arrays for that location. The response reports `mapping_status`:

* `ready`: every required binding resolves against the active catalog;
* `unresolved`: at least one item is missing or belongs to another catalog;
* `ambiguous`: a stable reference matches more than one catalog item.

Non-ready discounts remain visible to management clients but fail closed during ordering.

Organization fixed amounts and minimum-order thresholds require all active target locations to use one currency. A mixed-currency target set returns `discount_target_currency_mismatch`; per-location monetary overrides are not part of V1.

## Deactivation and history

Public API V1 does not expose destructive discount deletion. Deactivate a location discount or organization template with `PATCH { "enabled": false }`; it remains available for history and can be re-enabled with `PATCH { "enabled": true }` unless an internal lifecycle operation has already retired it after completed-order use. Existing retired location mappings remain readable with `status=retired`.
