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

# plan.item.updated

> One booking of a trip moved: it started booking, was confirmed, waits for your customer, or did not book.

One booking of a trip moved. Update that line of your trip tracker the moment it changes. Agentcard sends one `plan.item.updated` each time a flight, hotel or car in the plan changes state.

```json theme={null}
{
  "id": "evt_3a5c7e9b1d2f",
  "type": "plan.item.updated",
  "created": 1793318340,
  "livemode": true,
  "data": {
    "plan_id": "plan_8f2k4c1a9e7b3d5f6a2c8e0b",
    "version": 5,
    "user_id": "usr_8f3k2m",
    "external_user_id": "shopper-42",
    "conversation_id": "conv_9a8b7c6d5e4f3a2b1c0d9e8f",
    "item": {
      "key": "hotel",
      "kind": "hotel",
      "state": "needs_input",
      "previous_state": "booking",
      "name": "Memmo Alfama, 5 nights",
      "price_cents": 128400,
      "asked_cents": 131900,
      "confirmation": null,
      "depends_on": ["flight"],
      "reason": "price_changed"
    }
  }
}
```

## Follow a booking's states

| `state` | What happened |
| - | - |
| `approved` | Your customer approved the booking, and Agentcard books it once the bookings before it are confirmed. |
| `booking` | Agentcard is making the booking now. |
| `pending` | The supplier has not said yet whether the booking went through. Agentcard never books it a second time while it waits. |
| `confirmed` | The booking is confirmed. `confirmation` carries the supplier's number. |
| `needs_input` | The booking waits for your customer. `reason` says why. |
| `failed` | The supplier refused the booking, and nothing was charged for it. |
| `skipped` | The booking was not made, because a booking before it did not go through or nobody answered in time. |

## Answer a booking that waits

A `needs_input` booking carries one of two reasons:

* `price_changed`: the supplier asks a different price than your customer approved, in `asked_cents`. Agentcard never books at a price your customer did not see, up or down.
* `approval_required`: the payment asks your customer to approve it on their device.

Send your customer's answer to a changed price with `POST /buy/plans/:id/items/:key/answer`:

```bash theme={null}
curl -X POST https://api.agentcard.sh/buy/plans/plan_8f2k4c1a9e7b3d5f6a2c8e0b/items/hotel/answer \
  -H "Authorization: Bearer $SHOPPER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"answer": "accept_price"}'
```

`accept_price` books the item at the new price when the new price fits inside what your customer approved for the whole trip, which leaves room when another booking came in under its quote. A new price above that answers 409, and `difference_cents` is the amount above what the approval still covers:

```text theme={null}
{"error":"needs_approval","code":"needs_approval","difference_cents":3500}
```

The booking then keeps waiting, because a plan's approved total cannot be raised yet. Your customer can skip it instead.

`skip` leaves the booking unbooked, along with the bookings that wait on it. Bookings already confirmed stay booked: Agentcard never cancels one for your customer.

## Read a refused answer

| `code` | Status | What it means | What to do next |
| - | - | - | - |
| `needs_approval` | 409 | The new price is above what the trip's approval still covers, by `difference_cents`. A plan's approved total cannot be raised yet. | Tell your customer the booking costs more, and send `skip` if they decline it. |
| `not_waiting` | 409 | The booking is not waiting for an answer, or it waits on a payment approval on your customer's device. | Read the plan with `GET /buy/plans/:id` and follow the booking's `state`. |
| `hold_ended` | 409 | The answer came after `hold_until`. The bookings that waited are let go unbooked, and this endpoint can no longer book them. | Tell your customer those bookings were not made and nothing was charged for them. |
| `invalid_answer` | 400 | The body named no answer Agentcard takes. | Send `{"answer": "accept_price"}` or `{"answer": "skip"}`. |
| `plan_not_found` | 404 | No plan with this id belongs to this shopper and app. | Check the plan id and the shopper's access token. |

## Keep the newest version per booking

`version` is the plan's version at the change. Keep the highest `version` you have seen for each `item.key`, so a retried delivery for the hotel still applies after a newer delivery for the car.


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