Skip to content

Writing data

Fredrik Dettner edited this page Oct 14, 2026 · 4 revisions

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).

Identifying a property unit

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 the 201 body and the Location header 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.
  • name is your handle. Use it when your system does not keep the sedisId yet: GET property-units?name=… returns it, and an upload row may give name instead of sedisId. 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 sedisId and name on an upload row, they must name the same property unit (sedisIdNameMismatch otherwise).
  • 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 officialDesignation needs a municipalityId.
  • Only your own. A sedisId or a name only ever resolves among your own property units. Another customer's sedisId is unknownSedisId, 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.

The flow

  1. Look up the reference data you will send ids for — municipalities and property types.
  2. 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 the sedisId you get back.
  3. Upload the values for a value date (POST comp-uploads), naming each property unit by sedisId (or by its exact name). Send "submit": true when you want Sedis to review and publish them.
  4. Follow the upload with GET comp-uploads/{id} until it is published.

Property units

Look one up by your own name

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.

Create — POST /v2/fastighetsbenchmark/property-units

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.

Update or rename — PUT /v2/fastighetsbenchmark/property-units/{sedisId}

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.

  • 404 if the sedisId is unknown — or another customer's (indistinguishable on purpose).
  • 409 if the new name is taken by another of your property units.
  • Optimistic concurrency: send If-Match with the ETag from your last GET; if someone changed the property unit since, you get 412 Precondition Failed and nothing is written. Without If-Match the update always applies. (ETags are weak; If-Match compares the resource version.)
  • 200 OK with the updated property unit and its new ETag. No Idempotency-Key is needed — PUT is idempotent.

Sending a location

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.

Uploading values — POST /v2/fastighetsbenchmark/comp-uploads

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.

Following an upload — GET /v2/fastighetsbenchmark/comp-uploads/{id}

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.

Changing values — PATCH

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.

What waits for Sedis — GET …/property-units/{sedisId}/pending-changes

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.

Removing data — DELETE

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.

Strict: everything or nothing

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.

Reference data

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.

Related

Endpoints reference · Errors · Geometry · Multi-tenant isolation · Changelog

Clone this wiki locally