> For the complete documentation index, see [llms.txt](https://apidocs.akinon.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://apidocs.akinon.com/commerce-openapis/admin/basket-offers/partially-update-a-basket-offer.md).

# Partially update a basket offer

Partially updates a basket offer. Only the provided fields are changed; the validation rules described under **Update a basket offer** apply to the fields that are sent.

```json
{"openapi":"3.1.0","info":{"title":"Admin API","version":"1.0.0"},"tags":[{"name":"Basket Offers","description":"Administrative endpoints for **basket offers** — the promotion campaigns (discounts, coupons, voucher codes, free shipping, loyalty points, and similar benefits) that are evaluated against customer baskets on the storefront.\n\n## Core Capabilities\n\n**1. Basket Offer Listing & Filtering**\n* Retrieve a paginated list of basket offers, ordered so that offers ending soonest appear first.\n* Filter by status, offer type, voucher code, campaign dates, assigned user, label, and nested promotion / condition / benefit fields.\n\n**2. Basket Offer Lifecycle Management**\n* Create a basket offer together with its nested promotion, condition, and benefit in a single request.\n* Fully or partially update an existing basket offer.\n* Change the status of a single offer, or activate / deactivate many offers in one bulk request.\n\n**3. Campaign Composition**\n* A basket offer combines a **promotion** (identity), a **condition** (when the offer applies — quantity, amount, distinct-product, or free-form query rules), and a **benefit** (what the customer receives — percentage or fixed discount, multibuy pricing, free shipping, coupon or voucher generation, sample products, or loyalty points).\n* Offers can be restricted to a single user, a voucher code, both, or opened site-wide; bulk variants distribute coupons or voucher codes to many users.\n\n## Offer Types\n\nThe `offer_type` field determines how the offer is matched to a customer. When omitted on create, the server derives it from the presence of `user` and `voucher_code`.\n\n| Value | Description |\n|-------|-------------|\n| `sitewide` | Applies to every basket; no user and no voucher code may be set. |\n| `coupon` | Personal offer bound to a single user; no voucher code. |\n| `coupon_code` | Personal offer bound to a single user **and** redeemed with a voucher code. |\n| `voucher_code` | Public offer redeemed with a voucher code; no user binding. |\n| `bulk_voucher_code` | Offer redeemed through individually generated codes managed with the **Bulk Voucher Codes** endpoints (`/bulk_voucher_codes/`). |\n| `bulk_coupon` | Personal coupons distributed to a list of users uploaded as a file (`bulk_coupon_file`). |\n\n## Offer Statuses\n\n| Value | Description |\n|-------|-------------|\n| `active` | The offer is eligible for application on the storefront. |\n| `passive` | The offer is disabled. Expired offers are automatically moved to this status by a scheduled job. |\n| `used` | A single-use offer (e.g. a coupon) that has been consumed. A used offer's status cannot be changed again. |\n| `revoked` | The offer has been withdrawn. |\n\n## Dynamic Settings & Environment Variables\n\nThe behavior of these endpoints is influenced by the following dynamic settings, configured in the management panel. Each is referenced again in the description of the operations it affects.\n\n| Key | Type | Default | Effect |\n|-----|------|---------|--------|\n| `DEFAULT_CURRENCY` | string (a lowercase ISO 4217 currency code; must be one of the currencies configured in `AVAILABLE_CURRENCIES`) | the server configuration value `DEFAULT_CURRENCY_TYPE` | The shop's default currency. Affects **create** (`POST /basket_offers/`): when the `currencies` field is omitted from the request, the offer is created with `currencies` defaulting to a single-element list containing this currency. |\n| `BASKET_OFFER_IS_CONSUME_GROUP_ENABLED` | boolean | `false` | Controls whether consume-group settings are shown on the basket offer page of the management panel. This is a panel display toggle only — it does not change the validation or behavior of the API endpoints themselves. |\n\nTwo further dynamic settings of the promotions module — `AUTO_USE_COUPONS` and `PROMOTION_GATEWAY_ACTIVE` — govern how the offers created here are *applied to baskets on the storefront*; they have no effect on the administrative endpoints in this document.\n\n**Environment variables:** No environment variables are read directly by these endpoints. The only related server configuration value is `DEFAULT_CURRENCY_TYPE`, which serves as the fallback default of the `DEFAULT_CURRENCY` dynamic setting described above."}],"servers":[{"description":"Omnitron Remote Proxy (external access — recommended)","url":"https://{omnitron_url}/api/remote/{channel_id}","variables":{"omnitron_url":{"default":"sandbox.akinon.com","description":"Omnitron server URL (e.g., {omnitron.akinon.com})"},"channel_id":{"default":"1","description":"The channel identifier the remote request is routed through"}}},{"description":"Commerce API Server (internal / direct access only)","url":"https://{commerce_url}/api/v1","variables":{"commerce_url":{"default":"sandbox.akinon.com","description":"Internal commerce server URL, reachable only from within the Omnitron network"}}}],"security":[{"tokenAuth":[]}],"components":{"securitySchemes":{"tokenAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Token credential sent in the Authorization header, in the form: `Token <your-token>`. Requires a staff (admin) account."}},"schemas":{"BasketOfferRequest":{"type":"object","description":"The payload accepted when creating or updating a basket offer.","required":["promotion","condition","benefit","status"],"properties":{"label":{"type":["string","null"],"maxLength":512,"description":"Administrative label of the offer. Stored per language; the request language selects the translation being written."},"promotion":{"$ref":"#/components/schemas/Promotion"},"condition":{"$ref":"#/components/schemas/Condition"},"benefit":{"$ref":"#/components/schemas/Benefit"},"status":{"$ref":"#/components/schemas/BasketOfferStatus"},"offer_type":{"allOf":[{"$ref":"#/components/schemas/BasketOfferType"}],"description":"When omitted, derived from the presence of `user` and `voucher_code`."},"voucher_code":{"type":["string","null"],"maxLength":128,"description":"Voucher code redeeming the offer. Must be unique across all basket offers."},"user":{"type":["integer","null"],"description":"Identifier of the user the offer is assigned to, for personal offer types."},"is_visible":{"type":"boolean","default":true,"description":"Whether the offer is visible on the storefront."},"is_visible_on_list":{"type":"boolean","default":false,"description":"Whether the offer is visible on storefront listing pages."},"start_datetime":{"type":["string","null"],"format":"date-time","description":"Campaign start. Must precede `end_datetime`."},"end_datetime":{"type":["string","null"],"format":"date-time","description":"Campaign end. A past end date is only accepted together with `passive` status."},"priority":{"type":"integer","default":0,"description":"Application priority; offers with higher priority are evaluated first on the storefront."},"is_mergable":{"type":"boolean","default":true,"description":"When `false`, no further offers are applied to a basket after this offer."},"allowed_quantity_per_basket":{"type":"integer","minimum":1,"default":1,"description":"The maximum number of times the offer may be applied within a single basket."},"max_usage_per_user":{"type":"integer","default":0,"description":"The maximum number of times a single user may benefit from the offer. `0` means unlimited."},"max_stock_limit":{"type":["integer","null"],"minimum":0,"description":"The maximum total number of applications across all baskets. `0` means unlimited."},"currencies":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/Currency"},"description":"The currencies the offer is valid in. Defaults to the shop's default currency (see the `DEFAULT_CURRENCY` dynamic setting)."},"is_available_for_data_sources":{"type":"boolean","default":false,"description":"Whether the offer is exposed to marketplace data sources. When `true`, both the condition and the benefit must reference a static product collection."},"kwargs":{"type":["object","null"],"description":"Free-form extra configuration. When `data_source_discount_sharing_rate` is present it must be a number between 0 and 100."},"start_timedelta":{"type":["integer","null"],"minimum":0,"description":"Only for inner offers embedded in coupon / voucher benefits — validity start, in seconds relative to activation."},"end_timedelta":{"type":["integer","null"],"minimum":0,"description":"Only for inner offers embedded in coupon / voucher benefits — validity end, in seconds relative to activation."},"activation_timedelta":{"type":["integer","null"],"minimum":0,"description":"Only for inner offers embedded in coupon / voucher benefits — activation delay after purchase, in seconds. Exactly one of `activation_timedelta` and `activation_date` must be provided on the inner offer."},"activation_date":{"type":["string","null"],"format":"date-time","description":"Only for inner offers embedded in coupon / voucher benefits — absolute activation moment. Exactly one of `activation_timedelta` and `activation_date` must be provided on the inner offer."},"bulk_coupon_file":{"type":"string","contentEncoding":"base64","description":"Base64-encoded CSV or spreadsheet with an `email` column, listing the users that receive personal coupons. Cannot be combined with `user`. Turns the offer into a `bulk_coupon` offer; coupons are generated asynchronously."},"bulk_email_file":{"type":["string","null"],"contentEncoding":"base64","description":"Base64-encoded file of customer emails imported into the condition as a `bulk_email__in` rule. Processing is asynchronous; the offer is passive while the file is processed."},"bulk_phone_number_file":{"type":["string","null"],"contentEncoding":"base64","description":"Base64-encoded file of customer phone numbers imported into the condition as a `bulk_phone_number__in` rule. Processing is asynchronous; the offer is passive while the file is processed."}}},"Promotion":{"type":"object","description":"The identity of the campaign. The slug must be unique across all promotions.","required":["name"],"properties":{"pk":{"type":"integer","readOnly":true,"description":"Unique promotion identifier."},"name":{"type":"string","maxLength":255,"description":"Display name of the promotion."},"slug":{"type":"string","maxLength":255,"description":"Unique slug of the promotion. When omitted or blank, it is derived from the name. A duplicate slug is rejected."}}},"Condition":{"type":"object","description":"The rule that decides whether the offer applies to a basket.\n\nThe `kwargs` object carries the type-specific configuration. Required keys per `condition_type`:\n\n| `condition_type` | Required keys in `kwargs` |\n|------------------|----------------------------|\n| `quantity` | `price_type`, `consume_type`, `value`, and optionally `sub_conditions`, `excluded_sub_conditions`, `query`, `overlimit`, `distinct_by`, `distinct_by_attribute_key`, `data_sources` |\n| `amount` | `price_type`, `consume_type`, `value`, and optionally `sub_conditions`, `excluded_sub_conditions`, `query`, `overlimit`, `data_sources` |\n| `distinct` | `price_type`, `consume_type`, `value`, and optionally `sub_conditions`, `excluded_sub_conditions`, `query`, `overlimit` |\n| `query` | `consume_type`, `query` (must not be empty) |\n\n`query`, `sub_conditions`, and `excluded_sub_conditions` are lists of `[lookup, value]` (optionally `[lookup, value, data_type]`) pairs evaluated against basket, item, user, and pre-order attributes. `value` is the threshold quantity or amount; `overlimit`, when provided, must be greater than or equal to `value`. When `distinct_by` is `attribute`, `distinct_by_attribute_key` is required (and vice versa, `distinct_by_attribute_key` is only accepted together with `distinct_by=attribute`).\n\nAmount-based rules (`condition_type=amount` or `_amount` lookups inside the query lists) are rejected when the offer specifies more than one currency.","required":["condition_type","kwargs"],"properties":{"pk":{"type":"integer","readOnly":true,"description":"Unique condition identifier."},"condition_type":{"$ref":"#/components/schemas/ConditionType"},"product_collection":{"type":["integer","null"],"description":"Identifier of the product collection the condition is restricted to, when any."},"upsell_message":{"type":"string","maxLength":512,"description":"Optional storefront message encouraging the customer to complete the condition. When provided, it must contain the `{remaining}` placeholder."},"kwargs":{"type":"object","description":"Type-specific configuration of the condition (see the schema description)."}}},"ConditionType":{"type":"string","description":"The kind of rule that decides whether the offer applies to a basket.\n* `quantity` — a minimum quantity of matching items\n* `amount` — a minimum monetary amount of matching items\n* `distinct` — a minimum number of distinct matching products\n* `query` — a free-form rule expressed only through the `query` filter list","enum":["distinct","quantity","amount","query"]},"Benefit":{"type":"object","description":"What the customer receives when the condition is satisfied.\n\nThe `kwargs` object carries the type-specific configuration. Required keys per `benefit_type` (all types also accept the optional `max_discount_amount`):\n\n| `benefit_type` | Required keys in `kwargs` |\n|----------------|----------------------------|\n| `fixed` | `price_type`, `consume_type`, `amount` |\n| `percentage` | `price_type`, `consume_type`, `percentage` |\n| `multibuy` | `price_type`, `consume_type`, `item_count`, `sort_type`, `multibuy_discount_type`, plus `percentage` or `amount` depending on the discount type |\n| `shipping_free` | `price_type`, `consume_type` |\n| `coupon` | `price_type`, `consume_type`, `coupon` (an inner basket offer definition) |\n| `voucher` | `price_type`, `consume_type`, `coupon` (an inner basket offer definition) |\n| `sample_product` | `price_type`, `consume_type`, `allowed_quantity` |\n| `loyalty_point` | `price_type`, `consume_type`, `coupon`, `loyalty_point_coefficient`, `valid_from`, `valid_from_custom_date`, `valid_until`, `valid_until_custom_date` |\n\nFixed-amount benefits are rejected when the offer specifies more than one currency. A `shipping_free` benefit cannot be combined with payment-step conditions (`pre_order__payment_option`, `pre_order__card_info`, `pre_order__installment`).","required":["benefit_type","kwargs"],"properties":{"pk":{"type":"integer","readOnly":true,"description":"Unique benefit identifier."},"benefit_type":{"$ref":"#/components/schemas/BenefitType"},"product_collection":{"type":["integer","null"],"description":"Identifier of the product collection the benefit is restricted to, when any."},"kwargs":{"type":"object","description":"Type-specific configuration of the benefit (see the schema description)."}}},"BenefitType":{"type":"string","description":"What the customer receives when the condition is satisfied.\n* `percentage` — a percentage discount\n* `fixed` — a fixed-amount discount\n* `multibuy` — special pricing across a set of items (e.g. cheapest item free)\n* `shipping_free` — free shipping\n* `point` — loyalty points (legacy)\n* `coupon` — a personal coupon offer granted after purchase\n* `voucher` — a personal voucher-code offer granted after purchase\n* `sample_product` — free sample products added to the basket\n* `loyalty_point` — loyalty points credited to the customer's loyalty account","enum":["multibuy","percentage","fixed","shipping_free","point","coupon","voucher","sample_product","loyalty_point"]},"BasketOfferStatus":{"type":"string","description":"The lifecycle status of a basket offer.\n* `active` — eligible for application on the storefront\n* `passive` — disabled (expired offers are moved here automatically)\n* `used` — single-use offer that has been consumed; cannot be changed again\n* `revoked` — withdrawn","enum":["active","passive","used","revoked"]},"BasketOfferType":{"type":"string","description":"How the offer is matched to a customer. See the **Offer Types** section under **Basket Offers**.","enum":["sitewide","coupon","coupon_code","voucher_code","bulk_voucher_code","bulk_coupon"]},"Currency":{"type":"string","description":"A lowercase ISO 4217 currency code (for example `try`, `usd`, `eur`)."},"BasketOffer":{"allOf":[{"$ref":"#/components/schemas/BasketOfferRequest"},{"type":"object","description":"A basket offer as returned by the API.","properties":{"pk":{"type":"integer","description":"Unique basket offer identifier."},"user":{"type":["object","null"],"description":"When the offer is assigned to a user, the user is returned expanded as an object (identifier, email, name fields) rather than as a bare identifier."},"modified_date":{"type":"string","format":"date-time","description":"The moment the offer was last modified."},"remaining_stock_limit":{"type":"integer","description":"Only present when `max_stock_limit` is positive — the number of applications still available."}}}]},"ValidationError":{"type":"object","description":"Returned when the request contains invalid or missing data. Errors are grouped by the field they apply to: each key is the name of a field from the request and its value is a list of one or more messages describing what is wrong with that field. Messages that do not belong to any single field are grouped under `non_field_errors`.","properties":{"non_field_errors":{"type":"array","description":"Error messages that apply to the request as a whole rather than to a specific field.","items":{"type":"string"}}},"additionalProperties":{"type":"array","description":"The list of error messages for the field named by the key.","items":{"type":"string"}}},"BasketOfferBusinessError":{"type":"object","description":"Returned when a request is valid in form but violates a business rule of the promotion engine. The message describes the rule that was violated, and a stable code identifies it.\n\nCodes raised by these endpoints:\n* `promotion_100_1` — a promotion with the same slug already exists.\n* `promotion_100_2` — a basket offer with the same voucher code already exists.","properties":{"non_field_errors":{"type":"string","description":"A human-readable message describing the business rule that was violated."},"error_code":{"type":"string","description":"A stable code identifying the specific business rule violation."}},"additionalProperties":true},"Error":{"type":"object","description":"An error response.","properties":{"detail":{"type":"string","description":"A human-readable description of the error."}},"additionalProperties":true}},"responses":{"BasketOfferValidationOrBusinessError":{"description":"The request contains invalid or missing data, or violates a business rule — for example a promotion slug that already exists (`promotion_100_1`) or a voucher code that already exists (`promotion_100_2`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ValidationError"},{"$ref":"#/components/schemas/BasketOfferBusinessError"}]}}}},"Unauthorized":{"description":"Authentication credentials were not provided or are invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The authenticated user does not have administrator privileges.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"BasketOfferNotFound":{"description":"The requested basket offer does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/basket_offers/{id}/":{"patch":{"tags":["Basket Offers"],"operationId":"partialUpdateBasketOffer","summary":"Partially update a basket offer","description":"Partially updates a basket offer. Only the provided fields are changed; the validation rules described under **Update a basket offer** apply to the fields that are sent.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BasketOfferRequest"}}}},"responses":{"200":{"description":"The updated basket offer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BasketOffer"}}}},"400":{"$ref":"#/components/responses/BasketOfferValidationOrBusinessError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/BasketOfferNotFound"}}}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://apidocs.akinon.com/commerce-openapis/admin/basket-offers/partially-update-a-basket-offer.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
