Developers
Get access

Quickstart

Get an access token, then value a home. The samples include a shared sandbox credential, so you can copy, paste and run them without signing up. It takes under five minutes.

Before you start

You need curl, Node.js 20 or later, Python 3 with the requests package, or .NET 8.

The samples below already contain the sandbox credential:

Client ID
cms_test_01m41mt4emh9n42nz9nx42ca3f_9txzn5k8
Client secret
cms_sk_2XhUy_1uBHY1YIvYhpfPFNXYFLpxvI9nucj3IpU3t4s

1. Get an access token

The API uses OAuth 2.0 client credentials. Exchange the client ID and secret for a token:

curl -X POST https://auth.checkmystreet.co.uk/oauth2/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d grant_type=client_credentials \
  -d client_id=cms_test_01m41mt4emh9n42nz9nx42ca3f_9txzn5k8 \
  -d client_secret=cms_sk_2XhUy_1uBHY1YIvYhpfPFNXYFLpxvI9nucj3IpU3t4s
const tokenRes = await fetch("https://auth.checkmystreet.co.uk/oauth2/token", {
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  body: new URLSearchParams({
    grant_type: "client_credentials",
    client_id: "cms_test_01m41mt4emh9n42nz9nx42ca3f_9txzn5k8",
    client_secret: "cms_sk_2XhUy_1uBHY1YIvYhpfPFNXYFLpxvI9nucj3IpU3t4s",
  }),
});
const { access_token } = await tokenRes.json();
import requests

token_res = requests.post(
    "https://auth.checkmystreet.co.uk/oauth2/token",
    data={
        "grant_type": "client_credentials",
        "client_id": "cms_test_01m41mt4emh9n42nz9nx42ca3f_9txzn5k8",
        "client_secret": "cms_sk_2XhUy_1uBHY1YIvYhpfPFNXYFLpxvI9nucj3IpU3t4s",
    },
    timeout=10,
)
token_res.raise_for_status()
access_token = token_res.json()["access_token"]
using System.Net.Http.Json;
using System.Text.Json;

var http = new HttpClient();

var tokenRes = await http.PostAsync(
    "https://auth.checkmystreet.co.uk/oauth2/token",
    new FormUrlEncodedContent(new Dictionary<string, string>
    {
        ["grant_type"] = "client_credentials",
        ["client_id"] = "cms_test_01m41mt4emh9n42nz9nx42ca3f_9txzn5k8",
        ["client_secret"] = "cms_sk_2XhUy_1uBHY1YIvYhpfPFNXYFLpxvI9nucj3IpU3t4s",
    }));
tokenRes.EnsureSuccessStatusCode();

var tokenJson = await tokenRes.Content.ReadFromJsonAsync<JsonElement>();
var accessToken = tokenJson.GetProperty("access_token").GetString();

The response holds the token and its lifetime in seconds:

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 1800
}

Tokens last 30 minutes. Cache the token and reuse it until it expires, rather than requesting a new one for every call. Authentication covers caching and expiry.

For the curl samples, keep the token in a variable:

export TOKEN="paste-the-access-token-here"

2. Value a home

Send a POST to /partners/v1/valuations with the postcode, the property type and the number of bedrooms. This is the smallest valid request:

curl -X POST https://api.checkmystreet.co.uk/partners/v1/valuations \
  -H "Authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: 5f2b8c1e-4a7d-4e0b-9c61-2d8f3a90b7e4" \
  -H "Content-Type: application/json" \
  -d '{ "postcode": "M1 1AE", "propertyType": "flat", "bedrooms": 2 }'
const idempotencyKey = crypto.randomUUID(); // reuse this key if you retry

const res = await fetch("https://api.checkmystreet.co.uk/partners/v1/valuations", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${access_token}`,
    "Idempotency-Key": idempotencyKey,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ postcode: "M1 1AE", propertyType: "flat", bedrooms: 2 }),
});
const valuation = await res.json();
console.log(valuation.valuation.estimate); // 425000
import uuid

idempotency_key = str(uuid.uuid4())  # reuse this key if you retry

res = requests.post(
    "https://api.checkmystreet.co.uk/partners/v1/valuations",
    headers={
        "Authorization": f"Bearer {access_token}",
        "Idempotency-Key": idempotency_key,
    },
    json={"postcode": "M1 1AE", "propertyType": "flat", "bedrooms": 2},
    timeout=35,
)
valuation = res.json()
print(valuation["valuation"]["estimate"])  # 425000
var idempotencyKey = Guid.NewGuid().ToString(); // reuse this key if you retry

var request = new HttpRequestMessage(HttpMethod.Post,
    "https://api.checkmystreet.co.uk/partners/v1/valuations")
{
    Content = JsonContent.Create(new { postcode = "M1 1AE", propertyType = "flat", bedrooms = 2 }),
};
request.Headers.Authorization = new("Bearer", accessToken);
request.Headers.Add("Idempotency-Key", idempotencyKey);

var res = await http.SendAsync(request);
var valuation = await res.Content.ReadFromJsonAsync<JsonElement>();
Console.WriteLine(valuation.GetProperty("valuation").GetProperty("estimate")); // 425000

Send a new Idempotency-Key for each valuation you want, and reuse it only to retry that same request. However many times you retry with one key, you are charged once.

Request fields

FieldTypeRequiredNotes
postcodestringYesA full postcode in England or Wales.
propertyTypestringYesOne of detached, semi_detached, terraced, flat.
bedroomsintegerYes, unless you send floorAreaSqmUsed to estimate the floor area.
floorAreaSqmnumberNoFloor area in square metres, instead of bedrooms.
yearBuiltintegerNoThe year the property was built.
builtFormstringNoAllowed values are in the API reference.
wallsEnergyEfficiencystringNoAllowed values are in the API reference.
referencestringNoYour own case number, echoed back in the response.
includearrayNocommentary, rebuildCost or both. Free. See below.

3. Read the result

A successful call returns 201 Created and the valuation. Figures are in pounds.

{
  "id": "val_01j9xk2q7m4t8v6r3c5b0n1a2d",
  "reference": "case-10492",
  "valuedAt": "2026-11-03T10:15:02Z",
  "valuation": {
    "estimate": 425000,
    "range": { "low": 381000, "high": 472000, "coverage": 0.81 },
    "currency": "GBP",
    "indexedTo": "2026-08"
  },
  "location": { "sector": "M1 1", "localAuthority": "E08000003" },
  "dataQuality": "full",
  "model": { "version": "2026-09-28T15:05:18Z" },
  "input": { "postcode": "M1 1AE", "propertyType": "flat", "bedrooms": 2,
             "floorAreaSqm": 57, "floorAreaSource": "bedrooms" },
  "charge": { "credits": 10, "balanceAfter": 2490 }
}

Sandbox responses have the same shape, carry "mode": "test" and are never charged.

Low£381,000

Estimate£425,000

High£472,000

81% of past sales at this price level landed inside a range like this

In back-tests on 128,804 sales from May to July 2026, 81% of homes at this price level sold inside a range like this one. It describes the model across many sales, not the odds for this one property.
FieldWhat it tells you
valuation.estimateThe middle figure.
valuation.rangeThe low and high figures, and coverage: the share of past sales at this price level that landed inside a range like this one, in back-tests.
valuation.indexedToThe month the figures' price level stands at: the latest month the UK House Price Index had published for the area, usually about two months before valuedAt. The published past, not a forecast.
locationThe postcode sector and the ONS local authority code.
dataQualityHow complete the property data behind the valuation was.
model.versionThe model build that produced the figures.
inputWhat was valued, including anything we derived. Here the floor area came from the number of bedrooms.
chargeCredits this call used, and your balance afterwards.

Add commentary and the rebuild cost

Add include to the request for written commentary on the valuation and an indicative rebuild cost for buildings insurance. Both are free: the valuation costs 10 credits (10p) either way.

curl -X POST https://api.checkmystreet.co.uk/partners/v1/valuations \
  -H "Authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: 3c9a6f04-1d2e-4b7a-8f53-6e0b1a7c9d28" \
  -H "Content-Type: application/json" \
  -d '{ "postcode": "M1 1AE", "propertyType": "semi_detached", "bedrooms": 3,
        "include": ["commentary", "rebuildCost"] }'

The valuation comes back as above, with two more objects:

"commentary": {
  "summary": "Based on the characteristics provided and current market data, the estimated market value of this semi-detached property (85 m²) in the M1 1 postcode sector is £425,000. ...",
  "rangeWidth": "moderate",
  "rangeNote": "The estimate range is moderate: ...",
  "marketMomentum": "steady",
  "areaInsights": { "growth": "...", "overview": "..." },
  "disclaimer": "This estimate is produced by an automated statistical model ..."
},
"rebuildCost": {
  "estimated": true,
  "low": 196000, "typical": 231000, "high": 277000,
  "pricesAsOf": "2026-06"
}

The commentary is written from fixed templates, not by AI. Show its disclaimer with it. The rebuild cost is for houses: a flat comes back with "estimated": false and "reason": "flat", because a flat is insured on the block's policy. It is worked out from the details you send, so we do not check the home's construction or whether it is listed. The reference lists every field.

Street analysis, with the same token

Every product uses the same token and error format. For what surrounds a postcode, send a GET; reading the same postcode again within 30 days is free:

curl https://api.checkmystreet.co.uk/partners/v1/street-analysis/M11AE \
  -H "Authorization: Bearer $TOKEN"

The reference lists every field, and runs the request from the page.

4. Retry safely

The API stops any request that runs longer than 30 seconds. When a call fails in a way that is worth retrying, send it again with the same Idempotency-Key:

  • 504 timeout: retry with the same key. You are charged at most once.
  • 503 data-unavailable: try again shortly. This is never charged.
  • 409 request-in-progress: the first call with this key is still running. Wait, then retry.
  • 429: slow down, and wait the number of seconds given in Retry-After. If its code is daily_limit, stop until midnight UTC.

Limits and retries has the full policy.

Next steps

  • Testing: use magic postcodes to trigger each outcome before you go live.
  • Products: what is live now, and what comes next on the same token, headers and error format.
  • Get access: request your own test credentials, then go live after a first top-up by card.
  • Errors: every error type, what causes it and what to do.
  • API reference: every endpoint and field, from openapi.json.

Updated