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

# Stock Item Events

> Activities recorded in a stock item's timeline that track its lifecycle through orders, reservations, and notes.

<Frame caption="Inventory > Stock Items > [Item] > Events">
  <img src="https://mintcdn.com/twicecommerce/lZhc_tO8u1u_bL0Q/images/stock-item-events-tab.webp?fit=max&auto=format&n=lZhc_tO8u1u_bL0Q&q=85&s=1ae48153d760c337f141a2214978a78d" alt="Stock item events timeline" width="1920" height="1080" data-path="images/stock-item-events-tab.webp" />
</Frame>

## Definition

<Snippet file="definitions/event-definition.mdx" />

A Stock Item's **events** make up the timeline of everything that has happened to that item. TWICE distinguishes two layers:

1. **Scheduled events** — time-ranged blocks (reservations and notes) created by you or by automation. These can block availability and may carry attachments.
2. **Activity log events** — the system-recorded history of changes to the item (order assignment, fulfillment, status, location, attributes).

Together they answer the questions: *what is this item doing right now?* and *what has happened to it?*

<Info>
  **Analogy:** A Stock Item's events are its calendar plus its diary. The calendar (scheduled events) is the forward-looking view of what is committed; the diary (activity log) is the auditable record of everything that has happened.
</Info>

## Where do I use it?

Events are displayed in the [**Events**](/docs/inventory/stock-items/events) tab of each Stock Item. You work with events when:

* **Tracking item availability** — see what is blocking availability and when items will be free.
* **Recording customer orders** — order events are recorded automatically when items are assigned to orders.
* **Managing internal reservations** — block items for maintenance, storage, or internal use.
* **Adding documentation** — record inspections, condition notes, repair logs, or important observations.
* **Auditing item history** — reconstruct exactly when and why an item changed state, status, location, or SKU.
* **Reporting** — view all events across your inventory in one table.

## Scheduled events

Scheduled events are user-controlled and live on the article via `scheduledEvents`. Two types exist:

| Type          | Blocks availability | Customer-facing | Created by                    |
| ------------- | ------------------- | --------------- | ----------------------------- |
| `reservation` | Yes                 | No              | Operator (manual) or workflow |
| `note`        | No                  | No              | Operator (manual)             |

Both types carry the same shape:

```json theme={null}
{
  "id": "evt_abc123",
  "articleId": "art_xyz789",
  "type": "reservation",
  "name": "Yearly service",
  "comment": "Annual safety inspection",
  "startDate": "2025-06-01T08:00:00Z",
  "endDate": "2025-06-03T17:00:00Z",
  "serviceLocationId": "loc_helsinki",
  "tenantId": "tnt_001",
  "createdAt": "2025-05-15T12:00:00Z"
}
```

`endDate` can be `null` for open-ended events. Reservations with `null` end dates make the item unavailable until the reservation is closed.

### Reservations

Reservations create an `unavailability` range for the item. They are the way to take a Stock Item off the available pool for an internal reason — not a customer order — like maintenance, photo shoots, training, or holding an item for a known event.

* Manually created from the Stock Item's **Events** tab via **Add reservation**, or via `POST /articles/:id/scheduled-events`.
* During the reservation range, the item drops out of ATS and cannot be assigned to new orders.
* Once the end date passes, availability automatically returns. **Reservations expire on their own** — no manual cleanup required.
* A reservation can carry an attachment via the article ledger (`scheduledEventId` on a ledger entry) — e.g. log the repair cost against the reservation that scheduled the work.

<Tip>
  Prefer a reservation over **Out of use** when the unavailability has a known end date. Reservations expire automatically; **Out of use** requires manual reactivation. See [Stock Item Status](/docs/concepts/inventory/stock-item-status).
</Tip>

### Reservation priority

A manually-created reservation **takes precedence** over existing holds (orders and other reservations) when the stock item has no free capacity. TWICE first uses any free capacity, then rearranges existing holds into other free slots where possible, and only as a last resort releases the fewest existing holds needed to make room. Affected orders and reservations are **not cancelled** — only their hold on this specific stock item for the overlapping dates is released.

<Warning>
  Releasing a hold means the affected order or reservation no longer reserves that stock item for the overlapping period. The order itself remains active, but the stock item becomes unassigned for that window. You may need to assign a replacement stock item to the affected order.
</Warning>

<Frame caption="Reservation conflict confirmation dialog">
  <img src="https://mintcdn.com/twicecommerce/5ARkyCTk5wMAizBn/images/stock-item-reservation-conflict-dialog.webp?fit=max&auto=format&n=5ARkyCTk5wMAizBn&q=85&s=7a70b75becf71d40b2c11961ab7c3d45" alt="Confirmation dialog showing affected orders when creating a conflicting reservation" width="1920" height="1080" data-path="images/stock-item-reservation-conflict-dialog.webp" />
</Frame>

When the system determines that holds must be released, a **confirmation dialog** appears before anything changes. The dialog shows:

* The reservation you are adding (name, dates, location).
* A scrollable list of every order and reservation that will lose its hold on the stock item.
* Each affected row can be expanded to load details — order number, customer, status, and dates for orders; name and comment for reservations.
* An **"I understand the impact"** checkbox gates the confirm button.

If the set of affected holds changes between opening the dialog and confirming (for example, another operator adds a new order in between), TWICE asks you to review the updated list again before anything is released.

<Note>
  Only holds at the same service location as the reservation are affected. Holds on other locations for the same stock item remain untouched.
</Note>

### Notes

Notes are timestamped entries that do **not** block availability. Use them to document anything operational that should live on the item's record but is not a real-time commitment.

* Manually created from the Stock Item's **Events** tab via **Add note**, or via `POST /articles/:id/scheduled-events` with `type: 'note'`.
* Visible to operators with access to the item; never shown to customers.
* Can have an `endDate` if the observation covers a range (e.g. "condition observed Jan 10–15") or `null` for a single timestamp.
* Useful as a base for incident reports, condition history, and operational handoffs.

## Order events (activity log)

When an item is assigned to a customer order, TWICE records a stream of events in the activity log. These events are system-driven and not editable. The full set of system event types:

| `eventType`              | When it fires                                                | Context                                                              |
| ------------------------ | ------------------------------------------------------------ | -------------------------------------------------------------------- |
| `assigned_to_order`      | Item is added to an order                                    | `orderId`, `orderNumber`, `orderProductId`, `price`, `shopperId`     |
| `freed_from_order`       | Item is removed from an order or order is cancelled          | Same as above                                                        |
| `handed_out`             | Operator marks the line as picked up; state flips to **Out** | `orderId`, `orderNumber`, `shopperId`                                |
| `returned`               | Operator marks the line as returned; state flips to **In**   | `orderId`, `orderNumber`, `price`, `shopperId`, `orderProductId`     |
| `allocation_changed`     | The item's rental vs sales allocation changed                | `attributeChanges.from.allocation`, `attributeChanges.to.allocation` |
| `status_changed`         | Status changed (e.g. In use → Out of use)                    | `attributeChanges.from.status`, `attributeChanges.to.status`         |
| `sku_changed`            | SKU link changed                                             | `attributeChanges.from.sku`, `attributeChanges.to.sku`               |
| `location_changed`       | Service location changed                                     | `attributeChanges.from.storeId`, `attributeChanges.to.storeId`       |
| `identifiers_changed`    | `codes` array was updated                                    | `attributeChanges.from.itemCodes`, `attributeChanges.to.itemCodes`   |
| `specifications_changed` | Attributes or fixed field values changed                     | `attributeChanges.from`, `attributeChanges.to`                       |

Order events appear inline in the same Events timeline so you see both the commitments (reservations, notes) and the historical record together.

## Comparison

| Feature               | Order event                    | Reservation                  | Note                           |
| --------------------- | ------------------------------ | ---------------------------- | ------------------------------ |
| Source                | System                         | User or workflow             | User                           |
| Where managed         | Orders section                 | Stock Item Events tab        | Stock Item Events tab          |
| Blocks availability   | Yes (while line is active)     | Yes                          | No                             |
| Customer-facing       | Yes                            | No                           | No                             |
| Time-based            | Yes (rental or order period)   | Yes (reservation period)     | Optional (timestamp)           |
| Expires automatically | Yes (on return / cancellation) | Yes (at `endDate`)           | N/A                            |
| Carries attachments   | Via the order itself           | Via article ledger reference | Via article ledger reference   |
| Common use cases      | Customer rentals and sales     | Maintenance, internal hold   | Condition notes, incident logs |

## Where to manage events

<CardGroup cols={2}>
  <Card title="Customer Orders" icon="cart-shopping" href="/docs/orders/overview">
    Manage orders. Orders automatically record events on assigned Stock Items.
  </Card>

  <Card title="Internal Reservations and Notes" icon="calendar" href="/docs/inventory/stock-items/events">
    Add and manage reservations and notes from the Stock Item's Events tab.
  </Card>
</CardGroup>

<Info>
  The [Events](/docs/inventory/stock-items/events) tab shows scheduled events and the activity log together in chronological order, giving you a complete picture of the item's lifecycle.
</Info>

## Internal reservations vs holds

Reservations are the only way to "hold" inventory in TWICE outside of an order. Common patterns:

* **Maintenance window.** Block an item for a scheduled service period. Attach a ledger cost entry to the reservation for the repair invoice.
* **Photo shoot or training.** Block an item without involving the orders system.
* **Operator hold.** A customer is en route to pick up — create a short-range reservation so no one else can book that item.
* **Damage assessment.** Block the item until you have inspected and decided whether to return it to service.

Reservations cannot be converted into orders — they are a separate flow. If a customer wants an item you have reserved, delete or shorten the reservation and create a real order.

## Documents attached to events

Files can be attached to events through two mechanisms:

1. **Stock Item documents** (`documents` on the article) — global to the item.
2. **Article ledger entries with `scheduledEventId`** — financial entries tied to a specific reservation. The ledger entry can reference a file attachment as part of its `value` payload.

For example: a `Yearly service` reservation drives a `cost` ledger entry of `€150` with a PDF receipt attached. Both the reservation and the ledger entry stay linked, making the item's audit trail traceable end to end.

## Workflow triggers from events

Events are natural automation hooks. Common patterns:

* **On `handed_out`** → start a timer; flag the order as overdue if `returned` does not fire within `N` days.
* **On `returned`** → create a maintenance reservation if the order line was tagged as damaged.
* **On `status_changed` to Lost** → notify operations and open a ticket in your support system.
* **On reservation expiry** → automatically set status back to **In use** after a repair window closes.
* **On `assigned_to_order`** → write a webhook to your warehouse system to prepare the item.

Read more: [Workflows](/docs/workflows).

## Lifecycle

<Steps>
  <Step title="Creation">
    Events are created automatically (activity log) or manually (reservations, notes).

    <AccordionGroup>
      <Accordion title="How are order events created?">
        Automatically when an item is assigned to a customer order. The events fire in this typical sequence: `assigned_to_order` → `handed_out` → `returned`. Cancellations record `freed_from_order`.
      </Accordion>

      <Accordion title="How do I create a reservation?">
        Open the Stock Item, go to **Events**, click **Add reservation**, set the start and end dates and an optional name/comment. If the item is at full capacity for the requested range, a confirmation dialog shows which existing holds will be released before the reservation is created. API: `POST /articles/:id/scheduled-events` with `type: 'reservation'`.
      </Accordion>

      <Accordion title="How do I create a note?">
        Same flow as a reservation, but choose **Add note**. API: `POST /articles/:id/scheduled-events` with `type: 'note'`.
      </Accordion>

      <Accordion title="Can event creation be automated?">
        Yes. Use the API directly or trigger via workflows on customer order events, attribute changes, or external triggers.
      </Accordion>
    </AccordionGroup>
  </Step>

  <Step title="Display">
    Events appear in chronological order on the Events tab.

    <AccordionGroup>
      <Accordion title="Where do I see events?">
        Per-item: **Inventory > Stock Items > \[Item] > Events**. Across all items: **Inventory > Events**.
      </Accordion>

      <Accordion title="How are events sorted?">
        Chronologically, most recent first. The UI lets you filter by event type and date range.
      </Accordion>

      <Accordion title="What is shown for each event?">
        For scheduled events: start date, end date, type, name, comment, location. For activity-log events: timestamp, event type, the before/after values (`attributeChanges`) or the order context (`eventContext`).
      </Accordion>
    </AccordionGroup>
  </Step>

  <Step title="Modification">
    Scheduled events are editable; activity log entries are not.

    <AccordionGroup>
      <Accordion title="Can I edit order events?">
        Not directly. They are a system audit log. Modify the underlying order — the activity log will record the new transitions.
      </Accordion>

      <Accordion title="Can I edit a reservation?">
        Yes. `PUT /articles/:id/scheduled-events/:eventId` with the new fields. Or click the reservation in the timeline and edit. Availability recalculates immediately.
      </Accordion>

      <Accordion title="Can I edit a note?">
        Yes. Same endpoint as reservations.
      </Accordion>
    </AccordionGroup>
  </Step>

  <Step title="Deletion">
    Scheduled events can be deleted; activity log cannot.

    <AccordionGroup>
      <Accordion title="How do I delete a reservation?">
        Click the reservation and choose **Delete**, or `DELETE /articles/:id/scheduled-events/:eventId`. The blocked availability is released immediately.
      </Accordion>

      <Accordion title="How do I delete a note?">
        Same as reservations.
      </Accordion>

      <Accordion title="Can I delete order events?">
        No — they are the auditable history. Cancelling the underlying order will record `freed_from_order` (and possibly `returned` if applicable) but the original `assigned_to_order` event stays in the log.
      </Accordion>

      <Accordion title="Bulk delete?">
        `POST /articles/:id/scheduled-events/delete-many` accepts either explicit `ids` or `deleteAllExcept` semantics.
      </Accordion>
    </AccordionGroup>
  </Step>
</Steps>

## FAQs

<AccordionGroup>
  <Accordion title="Why would I use a reservation instead of an order?">
    Reservations are for internal blocks (maintenance, holds, photo shoots) without involving customers, payments, or order state. Orders are for customer-facing transactions.
  </Accordion>

  <Accordion title="Can I convert a reservation to an order?">
    No. They are separate entities. If a customer wants an item you reserved, delete the reservation and create a real order.
  </Accordion>

  <Accordion title="Do notes appear to customers?">
    No. Notes are internal-only and never displayed to customers.
  </Accordion>

  <Accordion title="Can I attach documents to events?">
    Yes. Documents on the Stock Item are always accessible from any event view. Article ledger entries can reference a specific `scheduledEventId` so financial attachments (invoices, receipts) stay associated with the reservation that triggered them.
  </Accordion>

  <Accordion title="How do events affect availability calculations?">
    Reservations and orders both block availability for the date range they cover. Notes do not. Activity-log events do not directly drive availability — they record what already happened.
  </Accordion>

  <Accordion title="Can I see all events across all stock items?">
    Yes — **Inventory > Events** gives you a unified table. Filter by event type, create custom views, group by Stock Item, and export for reporting. For individual item history, use the Stock Item's Events tab.
  </Accordion>

  <Accordion title="What happens if a reservation overlaps an order?">
    If a free capacity slot is available, the reservation takes it and the order is unaffected. If no free slot exists, TWICE attempts to reallocate existing holds to free slots non-destructively. Only when there is genuinely no room does the system ask you to confirm releasing the minimum set of existing holds. Affected orders are not cancelled — only their hold on that specific stock item is released. See [Reservation priority](#reservation-priority) for the full algorithm.
  </Accordion>

  <Accordion title="What are stock item conflicts on orders?">
    When a reservation releases a hold from an order, the affected stock item shows as **unavailable** on that order. The orders list displays a warning banner summarising the number of orders with conflicts, and the order's **Stock Items** tab highlights the conflict with a red counter. Assign a replacement stock item to resolve the conflict.
  </Accordion>
</AccordionGroup>

## Developer Reference

Scheduled events (reservations and notes) are exposed as `unavailabilities`. Activity log entries come from `audit-logs`.

<Card title="API: Unavailability" icon="code" href="https://server.twicecommerce.com/api/internal">
  Open the endpoint in the API reference.
</Card>

## Related Concepts

<CardGroup cols={2}>
  <Card title="Stock Items" icon="box" href="/docs/concepts/inventory/stock-items">
    Full Stock Item model and lifecycle
  </Card>

  <Card title="Stock Item State" icon="arrows-rotate" href="/docs/concepts/inventory/stock-item-state">
    How order events drive In/Out state
  </Card>

  <Card title="Stock Item Status" icon="circle-info" href="/docs/concepts/inventory/stock-item-status">
    Why status changes are recorded as events
  </Card>

  <Card title="Workflows" icon="diagram-project" href="/docs/workflows">
    Automate behaviour on events
  </Card>
</CardGroup>
