# Retrieve, replay & reconcile

Valuations are synchronous and there are no webhooks: the answer comes back in the response. This guide covers what to do when you did not get that response, how to read a recorded result again, and how to reconcile your records with ours.

## Three tools

| Tool | Use it when | Costs |
| --- | --- | --- |
| **Replay**: resend the same body with the same `Idempotency-Key` | You do not know whether a request completed | Free. Never charges twice. |
| **Read back**: `GET /v1/valuations/{request_id}` | You have the `request_id` and want the recorded result again | Free. Counts towards the per-minute rate limit. |
| **Console logs and usage CSV** | You want to audit or reconcile many requests | Free |

## Replay an unknown outcome

A timeout, a dropped connection or a crashed worker leaves you not knowing whether the valuation was recorded (and charged). Resend **exactly the same body with the same key**:

- If the first request finished, you get its recorded outcome back, valued, refused or failed, with `usage.idempotent_replay: true` and `usage.credits_used: 0`. `usage.original_credits_used` shows whether the original was charged.
- If it never arrived, the valuation runs now, once.
- If it is still running, you get `409` [`request_in_progress`](/docs/errors#request_in_progress). Wait briefly and replay again with the same key.

The body comparison ignores the order of JSON keys, but every value must be identical. A different body with the same key returns `409` [`idempotency_conflict`](/docs/errors#idempotency_conflict). Keys are scoped to your workspace and to test or live mode. [Idempotency](/docs/concepts/idempotency) has the full rules.

```json
{
  "usage": {
    "billable": false,
    "credits_used": 0,
    "original_credits_used": 0,
    "credits_remaining": 0,
    "cache_hit": false,
    "idempotent_replay": true,
    "mode": "test"
  }
}
```

> **Note:** A replay returns the recorded outcome, including a recorded failure. To make a **fresh attempt** after a confirmed `failed` or `refused` result, use a **new** key. See [errors & retries](/docs/errors).

## Read a result back

Store the `request_id` (`val_…`) from the response body; the `X-Valuation-Id` response header carries the same value. The `X-Request-Id` header is the HTTP request ID, which is a different value. To read the result later:

**curl**

```bash
curl https://data-services.autouncle.com/v1/valuations/val_0123456789abcdef0123456789abcdef \
  -H "Authorization: Bearer $AUTOUNCLE_API_KEY"
```

**Ruby**

```ruby
require "json"
require "net/http"

uri = URI("https://data-services.autouncle.com/v1/valuations/val_0123456789abcdef0123456789abcdef")
request = Net::HTTP::Get.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch("AUTOUNCLE_API_KEY")}"
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(request) }
puts JSON.pretty_generate(JSON.parse(response.body))
```

**Python**

```python
import json
import os

import requests

response = requests.get(
    "https://data-services.autouncle.com/v1/valuations/val_0123456789abcdef0123456789abcdef",
    headers={
        "Authorization": f"Bearer {os.environ['AUTOUNCLE_API_KEY']}",
    },
    timeout=30,
)
print(json.dumps(response.json(), indent=2))
```

**JavaScript**

```javascript
const response = await fetch("https://data-services.autouncle.com/v1/valuations/val_0123456789abcdef0123456789abcdef", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.AUTOUNCLE_API_KEY}`,
  },
});
console.log(JSON.stringify(await response.json(), null, 2));
```

The read-back:

- returns the result as it was recorded, including the `notes` and `attributions` that applied at the time, even if a source's notice has changed since;
- does **not** include the `usage` block;
- needs the `valuations:read` scope, and a key of the same mode: a test key cannot read a live result and vice versa;
- is private to your workspace. Another workspace's ID returns `404` [`not_found`](/docs/errors#not_found), as does an unknown ID.

Over MCP, the `get_valuation` tool returns the same result. See the [tool reference](/docs/mcp/tools).

## Why there is no polling loop

You never need to poll for completion: `POST /v1/valuations` returns the final outcome within its processing budget (about eight seconds; see [how valuations work](/docs/valuations)). The only "in progress" state you can observe is `request_in_progress`, when you replay a key whose first request has not finished. Wait a second or two and replay.

## Reconcile with your records

To make sure every vehicle you meant to value has an outcome:

1. **Before sending**, persist the idempotency key you will use with your own row, in state `pending`.
2. **After a response**, store `request_id`, `status` and the result, and mark the row done.
3. **On restart**, replay every row still `pending` with its stored key and body. Recorded rows come back for free; the rest are valued now.
4. **Periodically**, compare against the console:
   - **Request logs** lists recent requests with their status and request ID, and can be filtered by status (`valued`, `refused`, `failed`, `pending`) or by a specific request ID.
   - **Usage** shows requests and credits by day, week or month, and exports up to 10,000 rows as CSV with `request_id`, `date`, `mode`, `source`, `status`, `credits`, `duration_ms` and `country`.

`source` in the CSV tells you where a request came from: the REST API, MCP or the console playground.

## Re-valuing over time

A recorded valuation is a snapshot for its `valuation_date`. To value the same car again later (for example monthly for a fleet), send a new request with a **new** key that includes the date or period, such as `fleet-AB12345-2026-11`. Reusing last month's key would only replay last month's result.

## Pitfalls

- **Generating the key after the request.** If the key only exists in memory when the process dies, you cannot replay. Store it first.
- **Using the wrong header.** `GET /v1/valuations/{id}` needs the `val_…` ID from the body or the `X-Valuation-Id` header, not the `X-Request-Id` header.
- **Expecting usage on read-back.** Use the POST response, or the console, for billing details.

## Next steps

- [Idempotency](/docs/concepts/idempotency).
- [Batch & bulk valuations](/docs/guides/batch-valuations).
- [Production checklist](/docs/production-checklist).
