# State & recovery

Recover an uncertain write without creating a second booking, charge or financial obligation. Command acceptance and current resource state answer different questions.

## Persist before sending

Every mutation needs one valid UUID `Idempotency-Key`. Persist the UUID, operation, exact method/path/body and returned resource identities in your durable request record before sending. Quote/preview POSTs are reads and create no receipt; they do not require this header.

A response can contain `action=accepted`, `succeeded`, `action_required` or `unknown`. These are retained command acceptance facts, not a refreshed settlement or delivery ledger. The JSON envelope contains `data` and `request_id`; errors carry status/code/title/request ID and applicable validation/missing-input details.

## Resolve uncertain delivery

1. Keep the original UUID and submitted facts after a timeout, disconnect or uncertain response.
2. Retry the same method/path/body with that UUID and the same still-authorized key. Do not create another checkout or financial report to discover the first result.
3. Accepted replay returns the original status/resource identities with `replayed=true`. Changed normalized facts conflict rather than replace the command.
4. Follow the returned `resource_type`/`resource_id` to its current GET. Read actual payment, booking/session, approval, fulfillment and required-action state.
5. Use that resource's documented confirmation, retry or resolution capability. Each distinct command has its own persisted UUID; uncertain delivery reuses that command's UUID.

[Native checkout](/api/docs#/Studio%20native%20checkout/v2GetCheckout), [external checkout](/api/docs#/Studio%20external%20payments/v2GetExternalCheckout), [payment report](/api/docs#/Studio%20external%20payments/v2GetExternalPaymentReport), [amendment](/api/docs#/Studio%20booking%20aftercare/v2AftercareAmendment), [add-on purchase](/api/docs#/Studio%20booking%20aftercare/v2AftercareAddon), [cancellation](/api/docs#/Studio%20external%20recovery/v2GetCancellation) and [external refund](/api/docs#/Studio%20external%20recovery/v2GetExternalRefund) have separate current reads. A retained receipt does not become a live status response.

## Keep financial identities too

HTTP receipt scope includes the authorizing credential and operation. A replacement key with current permissions can recover a known tenant-owned resource, but cannot read the old key's private receipt.

Retain real collection/refund/cycle identities in addition to request UUIDs. A fresh HTTP UUID does not make an arbitrary second financial report a duplicate without the financial identity. Do not change a provider request identity while its result is undetermined or switch tender to discover the result.

## Interpret errors in context

| Result | Response |
| --- | --- |
| `401 invalid_key` | Correct missing, invalid or revoked credentials. Current authority still applies to recovery. |
| `403` | Resolve account, feature or permission refusal; do not escalate automatically. |
| `404 not_found` | The resource is absent or inaccessible under current contextual authority. |
| `409` | Inspect the operation-specific conflict, stale selection or reconciliation requirement. |
| `422 incomplete_selection` | Collect returned missing inputs; other validation/domain codes are operation-specific. |
| `503` | Retry infrastructure/calendar uncertainty only where documented; honor `Retry-After` and preserve write identity. |

An error is not universal proof that no money was collected. Log sanitized request IDs, UUIDs and returned resource IDs for support; never log studio keys, browser payment secrets or raw personal/payment payloads.

## What completion means

A paid resource can still await staff approval. Queued notifications have unknown delivery. A cancellation can retain an outstanding external refund obligation. Null/unsupported invoice facts are not an issued invoice. Read these facts explicitly instead of collapsing them into a single success flag.

Disabling new commercial entry preserves authorized accepted-resource reads/replay/recovery under current account/key/public-API authority. It does not bypass revocation or permission changes. If the sandbox/provider prerequisite is missing, the integration trial is blocked, not passed; public guide availability does not authorize writer enablement.

## Example

Send a complete saved booking request whose UUID and exact body were persisted before the first attempt:

```sh
curl "https://app.podyx.com/api/v2/bookings" \
  -H "Authorization: Bearer $PODYX_API_KEY" \
  -H "Idempotency-Key: $SAVED_BOOKING_UUID" \
  -H 'Content-Type: application/json' \
  --data-binary @saved-booking-request.json
```

If the accepted response was lost, resend that exact command. Once its native checkout identity is known, read current state:

```sh
curl "https://app.podyx.com/api/v2/checkouts/$CHECKOUT_ID" \
  -H "Authorization: Bearer $PODYX_API_KEY"
```

Use the returned resource type to choose the current GET. An external payable uses the external checkout read instead. A new intended booking gets a new UUID; retrying the same intent does not.
