# Quickstart

Go from a new account to your first valuation: first in the console playground, then from your own code. Everything here uses a free test key, so nothing is charged until you decide to go live. AutoUncle approves every new workspace before it can call the API, so allow for that review between steps 2 and 4.

## 1. Create your account

[Sign up](/signup) with your work email and a password. We send a verification email straight away.

- You can explore the console and create **test keys before you verify**.
- Verifying your email unlocks **30 signup credits** for live valuations. They are granted once per person, across all of your workspaces.

If the email does not arrive, use **Resend email** in the banner at the top of the console. A verification link expires after seven days.

## 2. Name your workspace

After signup you are asked for an organization name and to accept the [service terms](/legal/terms) on its behalf. This creates your **workspace**: it owns your API keys, credits, request logs and team. You become its owner.

**AutoUncle reviews every new workspace before it can use the API.** Until it is approved, the console shows a notice, and API, MCP and playground requests return `403` [`organization_pending`](/docs/errors#organization_pending). You can create keys and invite your team in the meantime.

You can invite colleagues later under **Settings**. Roles are explained in [authentication & keys](/docs/authentication#team-roles).

## 3. Create a test key

Open **API keys** in the console sidebar and create a key:

1. Give it a name you will recognise later, such as `local-development`.
2. Keep **Mode** set to **Test · simulated, free**.
3. Keep all five permissions selected for now. You can create narrower keys for production.
4. Leave countries empty to inherit your workspace's markets.
5. Choose **Create API key** and copy the secret. **It is shown only once.**

Store the key in an environment variable. Every example in this documentation reads it from `AUTOUNCLE_API_KEY`:

```bash
export AUTOUNCLE_API_KEY='au_test_...'
```

Never paste a key into source code, a browser app, a shared document or an agent prompt.

## 4. Run your first valuation in the playground

Open **Playground** in the console. Your test key is preselected and the request body already contains a 2020 Volkswagen Golf in Denmark. Choose **Run valuation →**.

You get a result in a second or two. Look at:

- **The price and currency**, with the price basis (`dealer_retail` by default).
- **The precision grade.** Test results are always `indicative`.
- **The resolved vehicle.** The catalogue matched the make and model, but more than one generation fits, so you see a `generation_ambiguous` warning.
- **Improvement hints**, such as picking the exact drivetrain from the catalogue.
- **Notes and data sources** at the bottom, including the `synthetic_result` note that marks a test result.

Switch the input to **Form** to pick a vehicle from the catalogue cascade, or switch the transport to **MCP** to run the same request through the `valuate_car` tool that agents use. The **Code** panel below always shows the request you are editing in curl, Ruby, Python and JavaScript.

## 5. Check your key from code

`GET /v1/account` is free and tells you whether a key works, which mode it is in and what it may do:

**curl**

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

**Ruby**

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

uri = URI("https://data-services.autouncle.com/v1/account")
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/account",
    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/account", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.AUTOUNCLE_API_KEY}`,
  },
});
console.log(JSON.stringify(await response.json(), null, 2));
```

A working test key returns `"mode": "test"`, its scopes, your workspace's markets and `rate_limit_per_minute`. A `401` means the key is missing, mistyped or revoked: see [errors](/docs/errors#invalid_api_key).

## 6. Value a vehicle from code

Send a `country` and what you know about the vehicle. Give every intended valuation its own `Idempotency-Key`, so you can retry it safely:

**curl**

```bash
curl https://data-services.autouncle.com/v1/valuations \
  -H "Authorization: Bearer $AUTOUNCLE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: first-valuation-001' \
  -d @- <<'JSON'
{
  "country": "DK",
  "vehicle": {
    "make": "Volkswagen",
    "model": "Golf",
    "model_year": 2020,
    "mileage": {
      "value": 60000,
      "unit": "km"
    }
  }
}
JSON
```

**Ruby**

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

uri = URI("https://data-services.autouncle.com/v1/valuations")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch("AUTOUNCLE_API_KEY")}"
request["Content-Type"] = "application/json"
request["Idempotency-Key"] = "first-valuation-001"
request.body = JSON.generate({
  "country" => "DK",
  "vehicle" => {
    "make" => "Volkswagen",
    "model" => "Golf",
    "model_year" => 2020,
    "mileage" => {
      "value" => 60000,
      "unit" => "km"
    }
  }
})
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.post(
    "https://data-services.autouncle.com/v1/valuations",
    headers={
        "Authorization": f"Bearer {os.environ['AUTOUNCLE_API_KEY']}",
        "Idempotency-Key": "first-valuation-001",
    },
    json={
        "country": "DK",
        "vehicle": {
            "make": "Volkswagen",
            "model": "Golf",
            "model_year": 2020,
            "mileage": {
                "value": 60000,
                "unit": "km"
            }
        }
    },
    timeout=30,
)
print(json.dumps(response.json(), indent=2))
```

**JavaScript**

```javascript
const response = await fetch("https://data-services.autouncle.com/v1/valuations", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.AUTOUNCLE_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": "first-valuation-001",
  },
  body: JSON.stringify({
    country: "DK",
    vehicle: {
      make: "Volkswagen",
      model: "Golf",
      model_year: 2020,
      mileage: {
        value: 60000,
        unit: "km"
      }
    }
  }),
});
console.log(JSON.stringify(await response.json(), null, 2));
```

[Open this request in the console playground](https://data-services.autouncle.com/console/playground?example=valuation)

The Ruby, Python and JavaScript versions need no extra libraries apart from `requests` for Python. Run the JavaScript example with Node.js 18 or later as an ES module, for example `node valuation.mjs`.

A successful response has `"status": "valued"`. Its main parts:

```json
{
  "request_id": "val_05f96b492a25a0ef9eb7aa99218a43be",
  "object": "valuation",
  "country": "DK",
  "mode": "test",
  "status": "valued",
  "vehicle": {
    "avs": { "version": "0.3", "kind": "vehicle" },
    "identity": {
      "brand": { "name": "VW", "ids": [{ "scheme": "autouncle", "value": "b-0957579dc5bca6de229d2f32" }] },
      "model": { "name": "Golf VII", "ids": [{ "scheme": "autouncle", "value": "cm-88dbede1978bc412872a6e1c" }] }
    },
    "vehicle": { "registration": { "country": "DK", "modelYear": 2020 }, "odometer": { "km": 60000 } }
  },
  "identification": { "status": "ambiguous", "level": "model" },
  "valuation": {
    "price": 102673,
    "currency": "DKK",
    "price_basis": "dealer_retail",
    "intervals": [{ "coverage": 0.8, "low": 82138, "high": 123208, "method": "synthetic" }]
  },
  "precision": { "grade": "indicative", "summary": "Synthetic sandbox result. Not a market valuation." },
  "improve_precision": [{ "field": "vehicle.catalogue.drivetrain_id", "reason": "drivetrain_unresolved", "expected_impact": "high" }],
  "notes": [{ "code": "synthetic_result", "category": "limitation" }],
  "usage": { "billable": false, "credits_used": 0, "idempotent_replay": false, "mode": "test" }
}
```

This is shortened; the [valuation result reference](/docs/reference/valuations#the-valuation-result) lists every field. Test prices are simulated. Never show them to users as market values.

Run the same command again with the same `Idempotency-Key`: you get the same result back with `"idempotent_replay": true`, and nothing is charged twice. Change the body but keep the key and you get `409 idempotency_conflict`. That is how [idempotency](/docs/concepts/idempotency) protects you from double charges.

## 7. Make the result more precise

The improvement hint asked for the exact drivetrain. Find it in the catalogue and send its ID instead of names:

**curl**

```bash
curl https://data-services.autouncle.com/v1/valuations \
  -H "Authorization: Bearer $AUTOUNCLE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: valuation-catalogue-001' \
  -d @- <<'JSON'
{
  "country": "DK",
  "vehicle": {
    "catalogue": {
      "drivetrain_id": "dv-947a3199394a5a4b41cb2869"
    },
    "model_year": 2021,
    "mileage": {
      "value": 45000,
      "unit": "km"
    }
  },
  "pricing": {
    "price_basis": "dealer_retail"
  }
}
JSON
```

**Ruby**

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

uri = URI("https://data-services.autouncle.com/v1/valuations")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch("AUTOUNCLE_API_KEY")}"
request["Content-Type"] = "application/json"
request["Idempotency-Key"] = "valuation-catalogue-001"
request.body = JSON.generate({
  "country" => "DK",
  "vehicle" => {
    "catalogue" => {
      "drivetrain_id" => "dv-947a3199394a5a4b41cb2869"
    },
    "model_year" => 2021,
    "mileage" => {
      "value" => 45000,
      "unit" => "km"
    }
  },
  "pricing" => {
    "price_basis" => "dealer_retail"
  }
})
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.post(
    "https://data-services.autouncle.com/v1/valuations",
    headers={
        "Authorization": f"Bearer {os.environ['AUTOUNCLE_API_KEY']}",
        "Idempotency-Key": "valuation-catalogue-001",
    },
    json={
        "country": "DK",
        "vehicle": {
            "catalogue": {
                "drivetrain_id": "dv-947a3199394a5a4b41cb2869"
            },
            "model_year": 2021,
            "mileage": {
                "value": 45000,
                "unit": "km"
            }
        },
        "pricing": {
            "price_basis": "dealer_retail"
        }
    },
    timeout=30,
)
print(json.dumps(response.json(), indent=2))
```

**JavaScript**

```javascript
const response = await fetch("https://data-services.autouncle.com/v1/valuations", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.AUTOUNCLE_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": "valuation-catalogue-001",
  },
  body: JSON.stringify({
    country: "DK",
    vehicle: {
      catalogue: {
        drivetrain_id: "dv-947a3199394a5a4b41cb2869"
      },
      model_year: 2021,
      mileage: {
        value: 45000,
        unit: "km"
      }
    },
    pricing: {
      price_basis: "dealer_retail"
    }
  }),
});
console.log(JSON.stringify(await response.json(), null, 2));
```

[Open this request in the console playground](https://data-services.autouncle.com/console/playground?example=valuation_catalogue)

The resolved vehicle now shows every level from brand to drivetrain, and the drivetrain hint is gone. [Build a catalogue picker](/docs/guides/catalogue-picker) shows the full cascade, and [improve precision](/docs/guides/improve-precision) explains each hint.

## 8. Go live

When your integration handles results and errors correctly with a test key:

1. **Verify your email** if you have not already, to receive your 30 signup credits. Check your balance under **Billing** or with `GET /v1/account`.
2. **Create a live key** under **API keys** with **Mode: Live · uses credits**. Give it only the scopes it needs, and consider a **monthly credit limit**.
3. **Swap the key** in your secret store. The code does not change: live and test keys use the same endpoints.
4. **Watch the first results** in **Request logs** and **Usage**.

A live valuation uses one credit only when it returns `"status": "valued"`. Refused and failed valuations, test valuations, catalogue lookups and account checks are free. For more credits, [contact sales](/contact-sales); packages appear under **Billing**. See [credits & billing](/docs/credits).

## 9. Before you launch

Work through the [production checklist](/docs/production-checklist): idempotency keys, retries with backoff, rate and concurrency limits, key hygiene and monitoring by request ID.

## Next steps

- [Value a listing](/docs/guides/value-a-listing): map your own data to a valuation request.
- [Connect an agent](/docs/mcp): use the same valuations from Claude, ChatGPT, Cursor and others.
- [API overview](/docs/api-reference): conventions, headers and every endpoint.
