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

# Hooks and history

> React in your app when an item changes state, and add your app's own events to a record's history.

## State hooks

`onState` on an inbox runs in your app whenever an item changes state, whether a person, a triage rule or a new occurrence moved it:

```ts theme={null}
export const pilots = inbox("pilots", {
  states: ["requested", "talking", "active", "converted", "dead"],
  closed: ["converted", "dead"],
  data: z.object({ company: z.string(), seats: z.number() }),
  onState: async ({ item, to }) => {
    if (to !== "converted") return
    await provisionSeats(item.data.company, item.data.seats)
  },
})
```

It receives the item (`id`, `title`, `record` and its typed `data`), the state it left (`from`), the state it's in now (`to`) and who moved it (`actor`). If the hook throws, the failure shows in the item's timeline; the state change itself stands.

## Record history

A record's page shows what was done to it in Pult. Your app can add its own events, so the person about to act sees what happened on your side too:

```ts theme={null}
await pult.log(user, user.id, "Changed plan to Pro", { by: user.username })
await pult.log(order, order.id, "Payment failed", {
  blocks: [b.fields({ reason: error.code })],
})
```

`by` says who did it in your app; without it the entry is from your app. Entries can carry [blocks](/build/blocks), and show up live on the record's page.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.