messpunkt.io Partner API · Quickstart
Preview V1 release candidate 1.0.0-rc.3 — production live since 30 September 2026; access per customer organisation on request: kontakt@messpunkt.io
5-Minute Walkthrough

Your first call against the sandbox

From zero to reading consumption data in four shell commands. Every step is copy-pasteable — pick a shell that has curl, python3, and openssl (macOS, Linux, or WSL).

What you'll have at the end: an access token scoped to the demo landlord "Musterhausverwaltung GmbH", a list of their Properties, and a warm-water consumption read-out with the meter-replacement demo scenario.

1Start the OAuth flow

The sandbox uses OAuth 2.1 Authorization Code + PKCE. First, generate a PKCE verifier + challenge pair — this proves later that the client that requested the code is the one redeeming it.

VERIFIER=$(openssl rand -base64 48 | tr -d '=+/' | head -c 64)
CHALLENGE=$(printf "%s" "$VERIFIER" | openssl dgst -binary -sha256 \
  | openssl base64 | tr -d '=' | tr '/+' '_-' | tr -d '\n')
echo "Verifier:  $VERIFIER"
echo "Challenge: $CHALLENGE"

In a real ERP flow the landlord's browser opens /oauth/authorize, the landlord signs in, picks Properties on the consent screen, and the authorization server redirects back with a code. For the quickstart we compress those steps: the sandbox's demo landlord is always signed in, so a single POST stands in for "the landlord approves". This shortcut exists only in the sandbox; the ERP guide, step 3 runs the real browser flow, including the iss check and the resource parameter that the demo client may leave out.

CODE=$(curl -s -D - -X POST \
  -d "client_id=sandbox-demo-client" \
  -d "redirect_uri=http://localhost:3000/callback" \
  -d "scope=read:units read:devices read:readings" \
  -d "state=quickstart" \
  -d "code_challenge=$CHALLENGE" \
  -d "code_challenge_method=S256" \
  -d "property=6fb74d25-5517-4dcc-ae8b-0914579ab036" \
  -d "decision=approve" \
  https://auth.sandbox.messpunkt.io/oauth/authorize -o /dev/null \
  | grep -i '^location:' | sed -E 's/.*[?&]code=([^&]*).*/\1/' | tr -d '\r\n')
echo "Got authorization code: $CODE"

2Exchange the code for a token

The code is an opaque base64url string (letters, digits, - and _); if $CODE is empty, print the location header without the pipe and look at the error parameter. The authorization code is single-use and expires after 5 minutes. Redeem it at /oauth/token, presenting the PKCE verifier:

curl -s -X POST \
  -d "grant_type=authorization_code" \
  -d "code=$CODE" \
  -d "client_id=sandbox-demo-client" \
  -d "redirect_uri=http://localhost:3000/callback" \
  -d "code_verifier=$VERIFIER" \
  https://auth.sandbox.messpunkt.io/oauth/token > token.json

TOKEN=$(python3 -c "import json; print(json.load(open('token.json'))['access_token'])")
echo "Access token (first 30 chars): ${TOKEN:0:30}..."

The response contains an access_token (1 hour lifetime), a refresh_token (expires after 90 days without use; there is no absolute cap, see ERP guide, step 5), and the granted scope. Save the refresh token for later — see Refreshing silently below:

REFRESH_TOKEN=$(python3 -c "import json; print(json.load(open('token.json'))['refresh_token'])")

3Identify yourself

Every ERP should call /v1/whoami after obtaining or refreshing a token to verify the tenant and Property scope:

curl -s -H "Authorization: Bearer $TOKEN" \
  https://api.sandbox.messpunkt.io/v1/whoami | python3 -m json.tool

Returns:

{
  "tenant_id": "3e17ba96-ae04-4d3b-9986-9e56f0adbf3a",
  "tenant_name": "Musterhausverwaltung GmbH",
  "client_id": "sandbox-demo-client",
  "granted_scopes": ["read:units", "read:devices", "read:readings"],
  "property_scope": ["6fb74d25-5517-4dcc-ae8b-0914579ab036"]
}

4Read consumption data

List the UsageUnits the landlord gave you access to, pick one, and request its warm-water consumption for a date range. The default sandbox data has a meter-replacement scenario on unit "WE 01" — you'll see two device segments in the response.

UNIT=$(curl -s -H "Authorization: Bearer $TOKEN" \
  https://api.sandbox.messpunkt.io/v1/usage-units \
  | python3 -c "import json,sys; print(json.load(sys.stdin)['data'][0]['id'])")

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://api.sandbox.messpunkt.io/v1/usage-units/$UNIT/consumption?from=2025-01-01&to=2025-12-31&metric=water_warm" \
  | python3 -m json.tool

The response gives you, per measuring point, one segment per device installation window. Each segment holds one reading per calendar month end (never finer) and a period_consumption block. The number to bill is period_consumption.billable_value — raw consumption × factor, measured from the segment's baseline_value — summed across segments when a meter was replaced mid-range. A meter a unit shares with other units carries the unit's unit_share; bill its weighted_billable_value for that unit. Do not compute last − first reading yourself: it misses the baseline, the start value of a replacement device and the K-factor. See Meter readings and consumption in the Reference for the full contract. Meters that belong to no unit (plant room, main meters) are not in /usage-units; list them per Property as described in the ERP guide.

Sandbox data is static. The synthetic fixture holds month-end values up to 2026-12-31 and is not extended automatically. From 2027 on, the latest months no longer look "current": a range reaching past December 2026 is shortened to end on 2026-12-31 (see the echoed to), and a range starting after it returns no values. The status substituted does not occur in the sandbox fixture — it is described in the Reference but cannot be tried out here.

Refreshing silently

When the 1-hour access token expires, exchange the refresh token for a fresh pair — no user interaction needed:

curl -s -X POST \
  -d "grant_type=refresh_token" \
  -d "refresh_token=$REFRESH_TOKEN" \
  -d "client_id=sandbox-demo-client" \
  https://auth.sandbox.messpunkt.io/oauth/token
Important: the response contains a new refresh token that supersedes the old one. Persist it immediately. Presenting the pre-rotation refresh token a second time is treated as token theft — the entire session is revoked and both tokens become useless. See the changelog and the Reference's Authentication section for the full replay-detection semantics.
Stuck or found a bug? Reach the maintainers at kontakt@messpunkt.io — pilot-partner feedback is actively invited.