# Orders, payments, applications. Sent once, or not at all.

Some forms change the world when they are sent: an order is placed, money moves, an application is filed. Kaabist records those steps just before and just after they run (a fence), so a crash, a retry or a redeploy can never send them twice.

## The problem

A script that times out right after clicking Submit cannot know whether the click went through. Retrying may order twice; not retrying may order nothing. Most automation tools simply retry.

## Fence the submit

Mark the step as a side effect and follow it with a checkpoint. Kaabist records the fence before the click and closes it once the step's expectation holds.

```
{ "click": { "role": "button", "name": "Place order" },
  "side_effect": true,
  "expect": { "url": "**/orders/*" } },
{ "checkpoint": "order-placed" }
```

## A crash pauses, it does not retry

When a server finds a fence still open, it does not click again. The job pauses as side_effect_ambiguous with a snapshot and a screenshot, and you check the site and decide.

## One job per order

Create each job with an Idempotency-Key. Repeating the call, after a timeout or a deploy, returns the job you already started instead of a second one.

```
curl https://api.kaab.ist/v1/jobs \
  -H "Authorization: Bearer $KAAB_API_KEY" \
  -H "Idempotency-Key: order-10482" \
  -d '{"program": "place-order", "inputs": {"sku": "HP-1037", "qty": 2}}'
```

## Rehearse without buying

Dry runs stop right before the first side effect. Test the whole checkout, with real pages and real validation, without placing an order.

## Questions

### Can I still retry a failed job?

Yes, from any checkpoint after the last side effect that ran. A retry cannot go back past a placed order.
