---
search:
  tags:
    - Events
    - POST
seo:
  description: >-
    The write side of the groups[].items array that GET /events/{id}… Reference
    for the POST /api/v1/events/{id}/items endpoint in the Bloomcount Public API
    API.
sidebar:
  label: Add, change and remove an event's lines
  badge: POST
title: Add, change and remove an event's lines
type: openapi-operation
---
The write side of the `groups[].items` array that `GET /events/{id}`
returns. A row **without** `itemId` creates a line; a row **with** one
updates it; a row with `remove: true` deletes it.

**Consumable lines** (the default) need a `variantId` and a
`supplierId` that sells it. The line's price is frozen at write time
from the event's price list, so changing the supplier re-freezes it.

**Hire lines** carry `mode: "hire"` with `hireStart` and `hireEnd`, and
need no supplier. They are checked against the variant's inventory
across every overlapping booking: a row that would overbook fails with
`hire_unavailable:<available>`. A line inside a group whose
`quantityMode` is `group` books `quantity × groupQuantity`, so the
multiplier counts toward that check.

Rows are independent and report their own errors; the event's totals
are recomputed once per call. Send an `Idempotency-Key` header to make
a retry safe.

Pass `groupId: null` to move a line out of its group; omitting `groupId` on an update leaves it where it is.

**Errors** (per row, in `errors`)

- `variant_id_required` / `variant_not_found` — a create row with no variant, or one that doesn't exist.
- `item_id_required` / `item_not_found` — an update or remove row naming no line, or one not on this event.
- `invalid_quantity` — quantity below 1, or not a whole number.
- `group_not_found` — `groupId` isn't a group on this event.
- `supplier_id_required` — a consumable create row with no supplier.
- `supplier_not_on_variant` — that supplier doesn't sell the variant.
- `supplier_not_allowed_on_hire` — hire lines take no supplier.
- `variant_not_hireable` — `mode: hire` on a variant that isn't hireable.
- `hire_dates_required` / `hire_end_before_start` — a hire line with missing or inverted dates.
- `not_a_hire_line` — hire dates sent for a consumable line.
- `hire_unavailable:<available>` — the booking would overbook the variant; the suffix is how many units are
  free across the requested window.

Whole-request failures: `404 event_not_found`, `400 items_must_be_array`, `422 too_many_items` above 500 rows.

<Operation source="reference" id="post-api-v1-events-id-items" />
