Repository navigation
Writing data
You can keep your Fastighetsbenchmark portfolio up to date from your own system: create and update your property units, and upload their values per value date. Sedis reviews submitted values before they are published into the benchmark.
Create with POST, update with PUT — an upload of values never creates a property unit.
Everything here is scoped to your API key's customer: you can only ever read or write your own property units and uploads (Multi-tenant isolation).
A property unit has three identifying fields. Only two of them can find it:
| Field | Who sets it | Unique | Can change | Finds the property unit |
|---|---|---|---|---|
sedisId |
Sedis, on create | Across Sedis | Never | Yes — always |
name |
You — your internal designation | Among your property units | Yes, with PUT
|
Yes — exact match, case-insensitive |
officialDesignation |
You — the land-registry designation, e.g. Klara 1:1 | No — in Sweden only together with the municipality | Yes, with PUT
|
No — it only describes the property |
-
Store the
sedisId. You get it in the201body and theLocationheader when you create a property unit, and back from every upload. It never changes, even when you rename the property unit. It is case-sensitive (v4ZIL9NafVo≠v4zil9nafvo) — keep it exactly as returned. -
nameis your handle. Use it when your system does not keep thesedisIdyet:GET property-units?name=…returns it, and an upload row may givenameinstead ofsedisId. Two of your property units can never share a name (409), so a name points at one property unit — until you rename it. -
Given both
sedisIdandnameon an upload row, they must name the same property unit (sedisIdNameMismatchotherwise). -
Rename with
PUT, never with an upload: an upload only reads the name, it does not change it. -
The official designation never matches. Two property units can share one, and in Sweden the same designation exists in many municipalities. That is also why a Swedish
officialDesignationneeds amunicipalityId. -
Only your own. A
sedisIdor a name only ever resolves among your own property units. Another customer'ssedisIdisunknownSedisId, exactly like one that never existed.
Excel upload works differently. The Excel upload in the Sedis web app matches the same way (Sedis Id, else Intern beteckning), but it is permissive: a row whose name matches none of your property units creates one, named by Intern beteckning or, if that is empty, Officiell beteckning; a row with a Sedis Id and a new Intern beteckning renames it; and if the same property unit is on several rows, the last row wins. The API is strict instead — an unknown name or a duplicate row is a
422, and nothing is created or renamed by an upload.
- Look up the reference data you will send ids for — municipalities and property types.
-
Find or create each property unit. Look it up by your own name for it (
GET property-units?name=…); if it does not exist, create it (POST property-units). Keep thesedisIdyou get back. -
Upload the values for a value date (
POST comp-uploads), naming each property unit bysedisId(or by its exact name). Send"submit": truewhen you want Sedis to review and publish them. -
Follow the upload with
GET comp-uploads/{id}until it ispublished.
curl -H "X-Api-Key: $SEDIS_API_KEY" \
"https://api.sedis.se/v2/fastighetsbenchmark/property-units?name=Kontoret%20Gladan%204"?name= is an exact match — case-insensitive, surrounding whitespace ignored — and returns zero or one property unit (more only if you already have duplicates, which Sedis can clean up for you). ?nameContains= is the substring search.
curl -X POST "https://api.sedis.se/v2/fastighetsbenchmark/property-units" \
-H "X-Api-Key: $SEDIS_API_KEY" -H "Content-Type: application/json" \
-H "Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7" \
-d '{
"name": "Kontoret Gladan 4",
"officialDesignation": "Gladan 4",
"municipalityId": 21,
"address": {
"streetNameAndNumber": "Sveavägen 12",
"postalCode": "111 57",
"postalTown": "Stockholm",
"countryCode": "SE"
},
"geometry": { "type": "Point", "coordinates": [18.0686, 59.3293] }
}'201 Created with a Location header, an ETag, and the property unit — the same shape as GET property-units/{sedisId}, including its new sedisId. The Idempotency-Key header is required: a retry with the same key returns the original response and creates nothing new.
| Field | Required | Rules |
|---|---|---|
name |
yes | Your name for it (internal designation). At most 300 characters. Unique among your property units (case-insensitive). |
officialDesignation |
no | The official property designation. In Sweden it is unique only together with the municipality, so a Swedish property unit with an officialDesignation needs municipalityId. |
municipalityId |
see above | An id from GET municipalities; must be in address.countryCode. |
address |
no | The postal address: streetNameAndNumber (≤ 600), postalCode (≤ 10), postalTown (≤ 100), countryCode (ISO 3166-1 alpha-2, default "SE"). The municipality and the official designation are not part of it — they are the property's administrative identity. |
geometry, geometryCrs
|
no | The property's location — see Sending a location. |
409 Conflict if you already have a property unit with that name. The response carries its existingSedisId — update it with PUT instead.
If you send no geometry, Sedis locates the property itself — from the official designation in Sweden (Lantmäteriet), otherwise from the address — and may complete address.postalCode and municipalityId from the address.
The same body as POST. PUT is a full replace: an optional field you leave out (or send as null) is cleared. Renaming happens here and only here.
-
404if thesedisIdis unknown — or another customer's (indistinguishable on purpose). -
409if the new name is taken by another of your property units. -
Optimistic concurrency: send
If-Matchwith theETagfrom your lastGET; if someone changed the property unit since, you get412 Precondition Failedand nothing is written. WithoutIf-Matchthe update always applies. (ETags are weak;If-Matchcompares the resource version.) -
200 OKwith the updated property unit and its newETag. NoIdempotency-Keyis needed —PUTis idempotent.
geometry is a GeoJSON Point (RFC 7946). coordinates is always [x, y]:
geometryCrs |
Coordinates | Example (Sergels torg) |
|---|---|---|
(omitted), http://www.opengis.net/def/crs/OGC/1.3/CRS84, CRS84, EPSG:4326
|
[longitude, latitude] — WGS 84 |
[18.0645, 59.3326] |
http://www.opengis.net/def/crs/EPSG/0/3006, EPSG:3006
|
[easting, northing] — SWEREF 99 TM |
[674322, 6581099] |
This is GeoJSON's order and the traditional GIS order that Lantmäteriet's own GeoJSON uses for SWEREF 99 TM — x before y, whatever the formal axis order of the coordinate system. RFC 7946 removed the crs member from GeoJSON, so the coordinate system goes in geometryCrs beside it. Only these coordinate systems are accepted.
Sedis checks the point and never corrects it — a point that does not add up is an error for you to fix:
- outside the coordinate system's range (
geometryOutOfRange) — usually swapped coordinates; - a Swedish property unit whose point is not in its municipality (
geometryOutsideMunicipality) or, without a municipality, not in Sweden (geometryOutsideCountry) — with a 200 m tolerance at boundaries; - a property unit outside Sweden whose point lies in Sweden (
geometryOutsideCountry).
A point you send is the property's location from then on; Sedis's own lookups never overwrite it. A PUT without geometry drops it, and Sedis locates the property again.
One upload = one value date. Each row names one of your property units and carries its values.
curl -X POST "https://api.sedis.se/v2/fastighetsbenchmark/comp-uploads" \
-H "X-Api-Key: $SEDIS_API_KEY" -H "Content-Type: application/json" \
-H "Idempotency-Key: 0b2f6e8e-3c1a-4c55-9a6e-2f1f3c9f7d10" \
-d '{
"valueDate": "2025-12-31",
"submit": true,
"rows": [
{ "sedisId": "v4ZIL9NafVo", "values": { "FN0": 412000000, "EA0": 1, "EB0": 2 } },
{ "name": "Kontoret Gladan 4", "values": { "FN0": 98000000, "FS0": null, "DA0": "2019-04-01" } }
]
}'Rows. 1–1000 rows (request body at most 5 MB). Name the property unit by sedisId, or by name matching exactly one of yours; given both, they must name the same one (Identifying a property unit). A property unit may appear on one row only. An unknown name is an error — an upload never creates a property unit.
Values are keyed by parameter code — base-data parameters only (isBaseData: true in GET parameters); codes are case-sensitive. The JSON type follows the parameter's dataType:
dataType |
JSON value | Example |
|---|---|---|
decimal |
number | 412000000 |
boolean |
true / false
|
true |
enum |
the integer from the parameter's enumValues (for EB0, an id from GET property-types) |
2 |
date |
ISO date string | "2019-04-01" |
null deletes the stored value; a code you leave out is left unchanged.
Value date. The end of a quarter (31 Mar, 30 Jun, 30 Sep, 31 Dec). Until quarterly and half-yearly data is released, only 31 December is accepted.
Submit. Without submit the upload is saved as uploaded: post again for the same value date to replace it. With "submit": true it goes to Sedis for review in the same call — and then every property unit must have a property classification (EA0) and a property type (EB0) on the value date, in the upload or already stored. Once submitted, the upload is Sedis's to publish: posting again for that date is 409 (with existingUploadId and existingStatus).
Response. 201 Created, Location: /v2/fastighetsbenchmark/comp-uploads/{id}, and the upload — with the sedisId each row was matched to, so your system learns the ids:
{
"id": 1234,
"valueDate": "2025-12-31",
"status": "submitted",
"uploadedOnUtc": "2026-10-05T09:12:44Z",
"rowCount": 2,
"rows": [
{ "index": 0, "sedisId": "v4ZIL9NafVo", "name": "Ekhagen 3" },
{ "index": 1, "sedisId": "pR7m2KdQ0z", "name": "Kontoret Gladan 4" }
],
"warnings": [
{ "message": "Avkastningskrav: 2 av 2 fastigheter: en hundradel av föregående värde – procent angiven som bråktal (0,065 i stället för 6,5)?", "code": "FR0" },
{ "message": "Ingående marknadsvärde (FS0) saknas och det finns inget marknadsvärde per 2024-12-31. Värdeförändring och avkastning blir 0 % per 2025-12-31.", "index": 1, "sedisId": "pR7m2KdQ0z" }
]
}Warnings (since 2.5.0) are remarks that do not stop the upload but that Sedis's review will look at — the same ones the Sedis web shows: a parameter that moved by the same factor on most property units against their earlier value date (often a wrong unit, such as a percentage sent as a fraction), a missing opening market value (FS0), a gap in the series. A remark on a whole parameter carries code; a remark on one row carries index and sedisId. The list is empty when there is nothing to remark. Check it before you send "submit": true; GET comp-uploads/{id} returns it too.
status |
Meaning |
|---|---|
uploaded |
Saved; you can replace it. An upload Sedis sends back for correction is uploaded again. |
submitted |
With Sedis for review. |
publishing |
Being published. |
published |
The values are live in Fastighetsbenchmark. |
Change some of a property unit's values at one value date without sending the rest. The body is a JSON Merge Patch of parameter codes, sent as application/merge-patch+json:
curl -X PATCH "https://api.sedis.se/v2/fastighetsbenchmark/property-units/v4ZIL9NafVo/values/2025-12-31" \
-H "X-Api-Key: $SEDIS_API_KEY" -H "Content-Type: application/merge-patch+json" \
-d '{ "FN0": 418000000, "FS0": null }'A code you leave out is unchanged; null removes the value; any other value is set, typed as for uploads. Base-data parameters only; the same 422 rules apply, with pointers like #/FN0. Sending the same patch twice changes nothing, so it needs no Idempotency-Key.
What happens depends on whether Sedis has shared the value date — whether it counts in the Sedis objects other customers compare themselves with:
| The value date is | Response | |
|---|---|---|
| not shared (only yours, or submitted and not yet published) |
200, status applied — or unchanged when every value was already stored |
Written at once and recalculated. |
| shared |
202 Accepted, status pending, Location: …/pending-changes
|
Not changed yet. The change waits for Sedis's review; the shared value stays until Sedis approves. |
{ "sedisId": "v4ZIL9NafVo", "valueDate": "2025-12-31", "status": "pending",
"changedParameterCodes": ["FN0", "FS0"], "pendingParameterCodes": ["FN0", "FS0"] }What it takes to be shared. Every response carries publishRequirements: { "complete": false, "missing": ["EB0"] } tells you the value date lacks a property type. A value date needs a property classification (EA0) and a property type (EB0) to be shared; data that is not shared may be incomplete. Removing EA0 or EB0 from a shared value date is 422.
A later patch of the same value replaces the change that waits, and patching the shared value back withdraws it — that is how you undo a correction. Sedis approves all of your waiting changes together, or sends them back with a comment.
One row per value date and parameter, typed like a comp-data row, with change (set or remove), source and changedOnUtc. When Sedis has sent your changes back, every row carries its reviewComment: correct with PATCH and Sedis reviews again. Once Sedis approves, the rows are gone and comp-data shows the new values.
| Request | Removes |
|---|---|
DELETE …/property-units/{sedisId}/values/{valueDate} |
every value of the property unit at that value date |
DELETE …/property-units/{sedisId} |
the property unit, its values and tags; it leaves your Samlingar |
204 when done; 404 for an unknown sedisId or a value date without values. Shared data cannot be removed through the API: it counts in the Sedis objects, and withdrawing it would change other customers' figures — 409 with type https://api.sedis.se/problems/shared-data; contact Sedis support. A sold property is not removed: report the sale as a transaction.
Writes are strict. If anything in the request breaks a rule, you get 422 Unprocessable Content listing every problem, and nothing is saved:
{
"type": "https://api.sedis.se/problems/validation",
"title": "The upload has errors.",
"status": 422,
"detail": "2 errors. Nothing was saved.",
"traceId": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
"errors": [
{ "pointer": "#/rows/0/sedisId", "code": "unknownSedisId",
"detail": "No property unit with sedisId 'OKAND123' exists for this customer. Create it with POST /v2/fastighetsbenchmark/property-units." },
{ "pointer": "#/rows/1/values/EB0", "code": "missingRequiredValue",
"detail": "EB0 is required to submit: every property unit needs a property classification (EA0) and a property type (EB0) on the value date — in this upload or already stored." }
]
}pointer is a JSON Pointer into your request body; code is stable and machine-readable. All codes: Errors.
| Resource | What | Use it for |
|---|---|---|
GET /v2/fastighetsbenchmark/municipalities (/{id}) |
id, name, countryCode, code — the official municipality code (Sweden: the four-digit SCB kommunkod, e.g. "0180"; null elsewhere) |
municipalityId. Map your own codes once with ?code=0180. Filters code, countryCode, nameContains. |
GET /v2/fastighetsbenchmark/property-types (/{id}) |
id, name
|
EB0 values, and the ?propertyType= filter. |
GET /v2/fastighetsbenchmark/parameters (/{code}) |
dataType, isBaseData, and enumValues for enum codes |
Which codes you can upload and what values they take. |
The ids are Sedis's and stable; the reference data is the same for every API key.
Endpoints reference · Errors · Geometry · Multi-tenant isolation · Changelog