# Asynchronous operations (/concepts/operations)



Sandbox lifecycle and filesystem mutations continue after the initial HTTP response.

## Accepted is not complete [#accepted-is-not-complete]

A create, pause, resume, or delete request returns a sandbox mutation:

```json
{
  "sandbox": {
    "id": "sbx_example",
    "state": "requested"
  },
  "operation": {
    "id": "op_example",
    "type": "sandbox_create",
    "state": "queued"
  }
}
```

Persist both IDs before waiting.

## States [#states]

Operations move through `queued`, `running`, and sometimes `reconciling`.

Only `succeeded`, `failed`, and `cancelled` are terminal.

A successful create should end with a `ready` sandbox. A successful delete should end with a `stopped` sandbox.

If the provider stops or deletes a `ready` sandbox on its own, OpenMetal moves it to `stopping` and then `stopped` with `state_reason` `provider_stopped`. Create a new sandbox to continue.

## Events [#events]

Operation events use increasing positive sequence numbers. The events endpoint returns finite SSE batches. Resume by passing the last handled sequence through `Last-Event-ID`, the SDK option, or CLI `--after`.

```ts
const events = await metal.operations.events(operation.id, {
  lastEventId: 42,
});
```

## Reconciliation [#reconciliation]

`reconciling` means the provider result is uncertain. OpenMetal avoids fallback because another attempt could duplicate live capacity.

<Callout type="warn" title="Bound your wait">
  If an operation remains `reconciling`, stop after a bounded wait and contact OpenMetal support
  with the operation and sandbox IDs.
</Callout>

See [common errors](/errors/common-errors) for safe retry rules.
