{"openapi":"3.1.0","info":{"title":"SDEP - Short-Term Rental Platform (STR) API","description":"Endpoints for short-term rental platforms to view areas, to submit and acknowledge listings (random checks), and to submit activities. Status: alpha. Changes from STR v1: adds the listing endpoints for random checks (`POST /listings/bulk`, `GET /listings`, `GET /listings/count`, `POST /listing-acknowledgements/bulk`); no other changes.","contact":{"name":"Nationaal Coordinator SDEP","url":"https://minvro.nl/","email":"nationaalcoordinatorsdep@minbzk.nl"},"version":"1.10.0"},"paths":{"/areas":{"get":{"tags":["str"],"summary":"Get all areas","description":"Get all areas, maximum 1000 per page. `limit` defaults to 1000 (the maximum); use `offset` and `limit` to page through the result set, and `GET /areas/count` for the total.\n\n**Each area contains:**\n- `areaId`: Functional ID identifying this area\n- `areaName`: Display name (optional) of the area\n- `regulation`: Regulation type of the area - 'listing', 'activity', or 'all'\n- `filename`: Name of the area shapefile (e.g., 'area.zip')\n- `competentAuthorityId`: Functional ID referencing the competent authority that owns the area\n- `competentAuthorityName`: Display name (optional) of the competent authority\n- `createdAt`: Timestamp when this area version was created (UTC)","operationId":"getAreasV2","security":[{"OAuth2ClientCredentials":[]}],"parameters":[{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Number of records to skip (default: 0)","default":0,"title":"Offset"},"description":"Number of records to skip (default: 0)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"description":"Maximum number of records to return (default: 1000, max: 1000)","default":1000,"title":"Limit"},"description":"Maximum number of records to return (default: 1000, max: 1000)"}],"responses":{"200":{"description":"List of areas","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AreaListResponse"},"example":{"areas":[{"areaId":"58ff0814-3aa1-5019-9afb-3cd9f398602c","areaName":"Amsterdam","regulation":"all","filename":"Amsterdam.zip","competentAuthorityId":"c4ac8ccf-a281-5789-bad7-28dfac20ca7f","competentAuthorityName":"Amsterdam (inclusief Weesp)","createdAt":"2025-01-01T00:00:00Z"},{"areaId":"974e2c23-b666-5044-a05c-9479a4c293a1","areaName":"Rotterdam","regulation":"all","filename":"Rotterdam.zip","competentAuthorityId":"a30df3a7-7e38-534c-b9c0-7666bad077d2","competentAuthorityName":"Rotterdam","createdAt":"2025-01-01T00:00:00Z"}]}}}},"500":{"description":"Internal Server Error - an unexpected issue occurred that prevented the request from being completed"},"503":{"description":"Service Unavailable - temporarily unable to process requests due to overload, maintenance, or dependency issues (database/authorization server)"},"400":{"description":"Bad request - invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized - missing or invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - insufficient permissions"}}}},"/areas/count":{"get":{"tags":["str"],"summary":"Get areas count (optional, to support pagination)","description":"Get areas count (optional, to support pagination).","operationId":"countAreas","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AreaCountResponse"}}}},"500":{"description":"Internal Server Error - an unexpected issue occurred that prevented the request from being completed"},"503":{"description":"Service Unavailable - temporarily unable to process requests due to overload, maintenance, or dependency issues (database/authorization server)"},"401":{"description":"Unauthorized - missing or invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - insufficient permissions"}},"security":[{"OAuth2ClientCredentials":[]}]}},"/areas/{areaId}":{"get":{"tags":["str"],"summary":"Get area (shapefile)","description":"Get area (shapefile) based on functional ID. The `areaId` is case-sensitive: use it exactly as returned by `GET /areas`.","operationId":"getArea","security":[{"OAuth2ClientCredentials":[]}],"parameters":[{"name":"areaId","in":"path","required":true,"schema":{"type":"string","title":"Areaid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/zip":{}}},"500":{"description":"Internal Server Error - an unexpected issue occurred that prevented the request from being completed"},"503":{"description":"Service Unavailable - temporarily unable to process requests due to overload, maintenance, or dependency issues (database/authorization server)"},"401":{"description":"Unauthorized - missing or invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - insufficient permissions"},"404":{"description":"Resource Not Found - area unavailable"}}}},"/activities/bulk":{"post":{"tags":["str"],"summary":"Submit activities in bulk for the currently authenticated platform","description":"Submit 1-1000 activities into the activities collection for the currently authenticated platform.\n\n**ID Pattern:**\n- `activityId` is provided by the platform as an optional business identifier (recommended UUIDv4, v5 or v8, RFC 9562); otherwise, it is generated by SDEP as a deterministic UUIDv8 (RFC 9562).\n- `activityId`, whether supplied or generated, remains permanently associated with exactly one platform, to ensure referential integrity.\n- `activityId` is case-sensitive and preserved exactly as submitted to support non-UUID identifiers as well (less recommended/unique). For example, `My3F2A` and `My3f2a` are treated as distinct IDs.\n- Keep the returned `activityId`: it is needed when wanting to update or correct the activity.\n\n**Versioning:**\n- No provided `activityId` + initial content → item OK with a new activity, with a generated `activityId`\n- No provided `activityId` + same content as before → item OK with the stored activity (same generated `activityId` and `createdAt`), nothing new is stored (idempotent)\n- No provided `activityId` + other content → item OK with a new activity, with a new generated `activityId`\n- New provided `activityId` + initial content → item OK with a new activity\n- Same provided `activityId` + same content as before → item OK with the stored activity, nothing new is stored (idempotent)\n- Same provided `activityId` + other content → item OK with a new version of the activity (an update or correction, e.g. `status` `cancelled`)\n- Content means all fields of the item, except `activityId`\n- Equal values count as the same content, e.g. the UTC offset `Z` counts as `+00:00` in a timestamp, an omitted `status` counts as `finished`, and `\"\"`, only spaces or `null` count as an omitted optional field\n- Unique constraint: (`activityId`, `createdAt`)\n- An `activityId` of another platform → item NOK (`duplicate_error`)\n- An item OK counts as succeeded, an item NOK as failed, see **Response HTTP status**\n\n**Validation flow (4 steps):**\n\n1. **Syntax and semantical validation** - each item is validated individually.\n   Failed items are marked NOK with the error reason; valid items continue.\n2. **Referential Integrity Check** - area IDs are verified. Items with unknown `areaId` are marked NOK; valid items continue.\n   Activities are rejected for areas that are regulated for listing only: such items are marked NOK with `regulation_error`.\n3. **Bulk Insert** - all remaining valid items are inserted in a single multi-row INSERT.\n4. **Feedback** - per-item OK/NOK response preserving original order.\n\n**Intra-batch duplicates (last-wins):**\nWhen the same `activityId` appears multiple times in a single batch, only the last\noccurrence is processed. Earlier occurrences receive NOK.\n\n**The request contains:**\n- `activities`: Array of activity objects to process (1-1000 items per batch)\n\n**Each activity item in the request contains:**\n- `activityId`: Functional ID identifying the activity (alphanumeric with hyphens `^[A-Za-z0-9\\-]+$`, max 64 chars, optionally supplied, auto-generated as deterministic UUIDv8 RFC 9562 if not supplied)\n- `activityName`: Display name of the activity (optional, max 64 chars)\n- `status`: Lifecycle status of the activity. Defaults to `finished` when omitted; may also be `cancelled`\n- `areaId`: Functional ID referencing the area where the activity took place\n- `url`: URL of the originating listing/advertisement (max 2048 chars)\n- `address`: Address composite (`thoroughfare`, `locatorDesignatorNumber` (optional), `locatorDesignatorLetter` (optional), `locatorDesignatorAddition` (optional), `postCode`, `postName`, `fullAddress`)\n- `registrationNumber`: Registration number of the address (max 128 chars)\n- `numberOfGuests`: Number of guests (1-1024)\n- `countryOfGuests`: Array of country codes of guests (1-1024; each element is ISO 3166-1 alpha-3 or `N/A`, uppercase only); array length must equal `numberOfGuests`.\n- `temporal`: Temporal composite (`startDatetime`, `endDatetime`), both in UTC with offset `Z` or `+00:00` (e.g. `2025-06-01T14:00:00Z`); rejected are other offsets such as CET (`2025-06-01T15:00:00+01:00`), no offset (`2025-06-01T14:00:00`) and no time (`2025-06-01`)\n\n**The response contains:**\n- `totalReceived`: Total number of items received in the request\n- `succeeded`: Number of items successfully created (status OK)\n- `failed`: Number of items that failed validation or processing (status NOK)\n- `results`: Per-item results preserving the original request order\n\n**Each results item contains:**\n- `activityIndex`: Zero-based index of this item in the original request list\n- `activityId`: As supplied in the request item, or `null` when it is missing or not a string\n- `status`: Processing result - `OK` (created successfully) or `NOK` (failed validation or processing)\n- `activity`: The full activity object (present for OK items, omitted for NOK items)\n- `errors`: Structured error details (present for NOK items, omitted for OK items)\n\n**The activity object (for the OK items) contains:**\n- `activityId`: Functional ID identifying this activity: as supplied in the request, or generated by SDEP (deterministic UUIDv8) when none was supplied\n- `activityName`: Display name (optional) of the activity\n- `status`: Lifecycle status of the activity: `finished` or `cancelled`\n- `areaId`: Functional ID referencing the area where this activity took place\n- `areaName`: Display name (optional) of the area where this activity took place\n- `competentAuthorityId`: Functional ID of the competent authority that owns the referenced area\n- `competentAuthorityName`: Display name (optional) of the competent authority\n- `url`: URL of the originating listing/advertisement\n- `address`: Address composite (`thoroughfare`, `locatorDesignatorNumber` (optional), `locatorDesignatorLetter` (optional), `locatorDesignatorAddition` (optional), `postCode`, `postName`, `fullAddress`)\n- `registrationNumber`: Registration number of the address (max 128 chars)\n- `numberOfGuests`: Number of guests (1-1024)\n- `countryOfGuests`: Array of country codes of guests (each element is ISO 3166-1 alpha-3 or `N/A`); array length equals `numberOfGuests`.\n- `temporal`: Temporal composite (startDatetime, endDatetime)\n- `platformId`: Functional ID referencing the platform that owns the activity\n- `platformName`: Display name (optional) of the platform\n- `createdAt`: Timestamp when this activity version was created (UTC)\n\n**Response HTTP status:**\n- 201: all items created successfully\n- 200: partial success (some OK, some NOK)\n- 401: missing or invalid token\n- 403: insufficient permissions\n- 409: a concurrent request wrote the same record first (`conflict_error`), retry the request\n- 422: all items failed","operationId":"postActivitiesBulkV2","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityBulkRequest"},"example":{"activities":[{"activityName":"Amsterdam Summer Rental","status":"finished","areaId":"58ff0814-3aa1-5019-9afb-3cd9f398602c","url":"http://example.com/amsterdam-myhouse-1","address":{"thoroughfare":"Prinsengracht","locatorDesignatorNumber":263,"locatorDesignatorLetter":"a","locatorDesignatorAddition":"II","postCode":"1016GV","postName":"Amsterdam","fullAddress":"Prinsengracht 263a-II, 1016GV Amsterdam"},"registrationNumber":"REG0001","numberOfGuests":4,"countryOfGuests":["NLD","NLD","DEU","BEL"],"temporal":{"startDatetime":"2025-06-01T14:00:00Z","endDatetime":"2025-06-07T11:00:00Z"}},{"activityName":"Rotterdam Weekend Stay","status":"cancelled","areaId":"974e2c23-b666-5044-a05c-9479a4c293a1","url":"http://example.com/rotterdam-apartment-2","address":{"thoroughfare":"Witte de Withstraat","locatorDesignatorNumber":45,"postCode":"3012BK","postName":"Rotterdam","fullAddress":"Witte de Withstraat 45, 3012BK Rotterdam"},"registrationNumber":"REG0002","numberOfGuests":2,"countryOfGuests":["FRA","FRA"],"temporal":{"startDatetime":"2025-07-12T15:00:00Z","endDatetime":"2025-07-14T10:00:00Z"}},{"activityName":"Amsterdam Canal House","areaId":"58ff0814-3aa1-5019-9afb-3cd9f398602c","url":"http://example.com/amsterdam-canal-house-3","address":{"thoroughfare":"Herengracht","locatorDesignatorNumber":100,"postCode":"1015BS","postName":"Amsterdam","fullAddress":"Herengracht 100, 1015BS Amsterdam"},"registrationNumber":"REG0003","numberOfGuests":3,"countryOfGuests":["GBR","GBR","IRL"],"temporal":{"startDatetime":"2025-08-10T11:00:00Z","endDatetime":"2025-08-05T14:00:00Z"}},{"activityName":"Rotterdam Harbor View","areaId":"974e2c23-b666-5044-a05c-9479a4c293a1","url":"http://example.com/rotterdam-harbor-view-4","address":{"thoroughfare":"Wilhelminakade","locatorDesignatorNumber":50,"postCode":"3072AP","postName":"Rotterdam","fullAddress":"Wilhelminakade 50, 3072AP Rotterdam"},"registrationNumber":"REG0004","numberOfGuests":1,"countryOfGuests":["ESP"]},{"activityName":"Groningen Loft","areaId":"00000000-0000-0000-0000-000000000000","url":"http://example.com/groningen-loft-5","address":{"thoroughfare":"Herestraat","locatorDesignatorNumber":20,"postCode":"9711LA","postName":"Groningen","fullAddress":"Herestraat 20, 9711LA Groningen"},"registrationNumber":"REG0005","numberOfGuests":2,"countryOfGuests":["ITA","ITA"],"temporal":{"startDatetime":"2025-09-01T14:00:00Z","endDatetime":"2025-09-03T10:00:00Z"}},{"activityName":"Amsterdam Studio","areaId":"58ff0814-3aa1-5019-9afb-3cd9f398602c","url":"http://example.com/amsterdam-studio-6","address":{"thoroughfare":"Keizersgracht","locatorDesignatorNumber":12,"postCode":"1015CS","postName":"Amsterdam","fullAddress":"Keizersgracht 12, 1015CS Amsterdam"},"registrationNumber":"REG0006","numberOfGuests":3,"countryOfGuests":["NLD","NLD"],"temporal":{"startDatetime":"2025-10-01T14:00:00Z","endDatetime":"2025-10-03T10:00:00Z"}}]}}},"required":true},"responses":{"201":{"description":"All activities created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityBulkResponse"},"example":{"totalReceived":2,"succeeded":2,"failed":0,"results":[{"activityIndex":0,"activityId":"550e8400-e29b-41d4-a716-446655440000","status":"OK","activity":{"activityId":"550e8400-e29b-41d4-a716-446655440000","status":"finished","areaId":"58ff0814-3aa1-5019-9afb-3cd9f398602c","competentAuthorityId":"c4ac8ccf-a281-5789-bad7-28dfac20ca7f","competentAuthorityName":"Amsterdam (inclusief Weesp)","url":"http://example.com/amsterdam-myhouse-1","address":{"thoroughfare":"Prinsengracht","locatorDesignatorNumber":263,"postCode":"1016GV","postName":"Amsterdam","fullAddress":"Prinsengracht 263, 1016GV Amsterdam"},"registrationNumber":"REG0001","numberOfGuests":4,"countryOfGuests":["NLD","DEU","BEL","N/A"],"temporal":{"startDatetime":"2025-06-01T14:00:00Z","endDatetime":"2025-06-07T11:00:00Z"},"platformId":"8e70f1e2-4c61-477b-89b8-0dbf25ab8b21","platformName":"Test STR 01","createdAt":"2025-06-01T12:00:00Z"}},{"activityIndex":1,"activityId":"660f9511-f30c-52e5-b827-557766551111","status":"OK","activity":{"activityId":"660f9511-f30c-52e5-b827-557766551111","status":"cancelled","areaId":"974e2c23-b666-5044-a05c-9479a4c293a1","competentAuthorityId":"a30df3a7-7e38-534c-b9c0-7666bad077d2","competentAuthorityName":"Rotterdam","url":"http://example.com/rotterdam-apartment-2","address":{"thoroughfare":"Witte de Withstraat","locatorDesignatorNumber":45,"postCode":"3012BK","postName":"Rotterdam","fullAddress":"Witte de Withstraat 45, 3012BK Rotterdam"},"registrationNumber":"REG0002","numberOfGuests":2,"countryOfGuests":["FRA","FRA"],"temporal":{"startDatetime":"2025-07-12T15:00:00Z","endDatetime":"2025-07-14T10:00:00Z"},"platformId":"8e70f1e2-4c61-477b-89b8-0dbf25ab8b21","platformName":"Test STR 01","createdAt":"2025-06-01T12:00:00Z"}}]}}}},"500":{"description":"Internal Server Error - an unexpected issue occurred that prevented the request from being completed"},"503":{"description":"Service Unavailable - temporarily unable to process requests due to overload, maintenance, or dependency issues (database/authorization server)"},"200":{"description":"Partial success - some activities created, some failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityBulkResponse"},"example":{"totalReceived":7,"succeeded":2,"failed":5,"results":[{"activityIndex":0,"activityId":null,"status":"OK","activity":{"activityId":"550e8400-e29b-41d4-a716-446655440000","activityName":"Amsterdam Summer Rental","status":"finished","areaId":"58ff0814-3aa1-5019-9afb-3cd9f398602c","competentAuthorityId":"c4ac8ccf-a281-5789-bad7-28dfac20ca7f","competentAuthorityName":"Amsterdam (inclusief Weesp)","url":"http://example.com/amsterdam-myhouse-1","address":{"thoroughfare":"Prinsengracht","locatorDesignatorNumber":263,"locatorDesignatorLetter":"a","locatorDesignatorAddition":"II","postCode":"1016GV","postName":"Amsterdam","fullAddress":"Prinsengracht 263a-II, 1016GV Amsterdam"},"registrationNumber":"REG0001","numberOfGuests":4,"countryOfGuests":["NLD","NLD","DEU","BEL"],"temporal":{"startDatetime":"2025-06-01T14:00:00Z","endDatetime":"2025-06-07T11:00:00Z"},"platformId":"8e70f1e2-4c61-477b-89b8-0dbf25ab8b21","platformName":"Test STR 01 (interactive usage, persistent)","createdAt":"2026-04-17T12:31:45.492466Z"}},{"activityIndex":1,"activityId":null,"status":"OK","activity":{"activityId":"660f9511-f30c-52e5-b827-557766551111","activityName":"Rotterdam Weekend Stay","status":"cancelled","areaId":"974e2c23-b666-5044-a05c-9479a4c293a1","competentAuthorityId":"a30df3a7-7e38-534c-b9c0-7666bad077d2","competentAuthorityName":"Rotterdam","url":"http://example.com/rotterdam-apartment-2","address":{"thoroughfare":"Witte de Withstraat","locatorDesignatorNumber":45,"postCode":"3012BK","postName":"Rotterdam","fullAddress":"Witte de Withstraat 45, 3012BK Rotterdam"},"registrationNumber":"REG0002","numberOfGuests":2,"countryOfGuests":["FRA","FRA"],"temporal":{"startDatetime":"2025-07-12T15:00:00Z","endDatetime":"2025-07-14T10:00:00Z"},"platformId":"8e70f1e2-4c61-477b-89b8-0dbf25ab8b21","platformName":"Test STR 01 (interactive usage, persistent)","createdAt":"2026-04-17T12:31:45.492466Z"}},{"activityIndex":2,"activityId":null,"status":"NOK","errors":{"detail":[{"msg":"Value error, End datetime must be after start datetime","type":"value_error","loc":["temporal","endDatetime"]}]}},{"activityIndex":3,"activityId":null,"status":"NOK","errors":{"detail":[{"msg":"Field required","type":"missing","loc":["temporal"]}]}},{"activityIndex":4,"activityId":null,"status":"NOK","errors":{"detail":[{"msg":"Area with areaId '00000000-0000-0000-0000-000000000000' not found","type":"not_found_error","loc":["areaId"]}]}},{"activityIndex":5,"activityId":null,"status":"NOK","errors":{"detail":[{"msg":"Value error, numberOfGuests (3) must equal the number of elements in countryOfGuests (2)","type":"value_error","loc":[]}]}},{"activityIndex":6,"activityId":null,"status":"NOK","errors":{"detail":[{"msg":"Area with areaId '00c0748b-5782-5d7e-be01-7dd306841d89' is regulated for listing only","type":"regulation_error","loc":["areaId"]}]}}]}}}},"401":{"description":"Unauthorized - missing or invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - insufficient permissions"},"409":{"description":"Conflict - a concurrent request wrote the same record first (`conflict_error`), retry the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"All activities failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityBulkResponse"},"example":{"totalReceived":2,"succeeded":0,"failed":2,"results":[{"activityIndex":0,"activityId":"550e8400-e29b-41d4-a716-446655440000","status":"NOK","errors":{"detail":[{"msg":"Area with areaId '00000000-0000-0000-0000-000000000000' not found","type":"not_found_error","loc":["areaId"]},{"msg":"Value error, End datetime must be after start datetime","type":"value_error","loc":["temporal","endDatetime"]}]}},{"activityIndex":1,"activityId":null,"status":"NOK","errors":{"detail":[{"msg":"Area with areaId '00000000-0000-0000-0000-000000000000' not found","type":"not_found_error","loc":["areaId"]},{"msg":"Field required","type":"missing","loc":["temporal"]}]}}]}}}}},"security":[{"OAuth2ClientCredentials":[]}]}},"/listings/bulk":{"post":{"tags":["str"],"summary":"Submit randomly selected listings in bulk for the currently authenticated platform","description":"Submit 1-1000 randomly selected listings for screening (random checks, see the functional design). Every submitted listing starts `pending`; the listing screening authority sets it to `clear` or `flagged`, and the platform acknowledges flagged listings via `POST /listing-acknowledgements/bulk`.\n\n**ID Pattern:**\n- `listingId` is provided by the platform as an optional business identifier (recommended UUIDv4, v5 or v8, RFC 9562); otherwise, it is generated by SDEP as a deterministic UUIDv8 (RFC 9562).\n- `listingId`, whether supplied or generated, remains permanently associated with exactly one platform, to ensure referential integrity.\n- `listingId` is case-sensitive and preserved exactly as submitted to support non-UUID identifiers as well (less recommended/unique). For example, `My3F2A` and `My3f2a` are treated as distinct IDs.\n- Keep the returned `listingId`: it is needed when wanting to correct the listing.\n\n**Versioning:**\n- No provided `listingId` + initial content → item OK with a new `pending` listing, with a generated `listingId`\n- No provided `listingId` + same content as before → item OK with the stored listing (same generated `listingId` and `createdAt`), nothing new is stored, whatever its status (idempotent)\n- No provided `listingId` + other content → item OK with a new `pending` listing, with a new generated `listingId`\n- New provided `listingId` + initial content → item OK with a new `pending` listing\n- Same provided `listingId` + same content as before → item OK with the stored listing, nothing new is stored, whatever its status (idempotent)\n- Same provided `listingId` + other content → item OK with a new `pending` version (a correction), only while the listing is `pending`\n- Same provided `listingId` + other content, once screened (`clear`, `flagged`, `acknowledged`) → item NOK (`conflict_error`): submit it under a new `listingId` instead (a new random check)\n- Content means all fields of the item, except `listingId`\n- Equal values count as the same content, e.g. `\"\"`, only spaces or `null` count as an omitted optional field\n- Unique constraint: (`listingId`, `createdAt`)\n- A `listingId` of another platform → item NOK (`duplicate_error`)\n- An item OK counts as succeeded, an item NOK as failed, see **Response HTTP status**\n\n**Validation flow (4 steps):**\n\n1. **Syntax and semantical validation** - each item is validated individually.\n   Failed items are marked NOK with the error reason; valid items continue.\n2. **Referential Integrity Check** - area IDs are verified. Items with unknown `areaId` are marked NOK (`not_found_error`).\n   Listings are rejected for areas that are regulated for activity only (`regulation` is `activity`): such items are marked NOK with `regulation_error`.\n3. **Versioning and Bulk Insert** - the current version is locked and checked (`pending`), marked ended, and all remaining valid items are inserted as new versions in a single multi-row INSERT.\n4. **Feedback** - per-item OK/NOK response preserving original order.\n\n**Intra-batch duplicates (last-wins):**\nWhen the same `listingId` appears multiple times in a single batch, only the last\noccurrence is processed. Earlier occurrences receive NOK.\n\n**The request contains:**\n- `listings`: Array of listing objects to process (1-1000 items per batch)\n\n**Each listing item in the request contains:**\n- `listingId`: Functional ID identifying the listing (alphanumeric with hyphens `^[A-Za-z0-9\\-]+$`, max 64 chars, optionally supplied, auto-generated as deterministic UUIDv8 RFC 9562 if not supplied)\n- `listingName`: Display name of the listing (optional, max 64 chars)\n- `areaId`: Functional ID referencing the area where the listing is posted\n- `url`: URL referencing the listing online (max 2048 chars)\n- `address`: Address composite (`thoroughfare`, `locatorDesignatorNumber` (optional), `locatorDesignatorLetter` (optional), `locatorDesignatorAddition` (optional), `postCode`, `postName`, `fullAddress`)\n- `declaredAsShortTermRental`: Host self-declaration (`true` or `false`)\n- `registrationNumber`: Registration number shown on the listing (optional, max 128 chars)\n\n**The response contains:**\n- `totalReceived`: Total number of items received in the request\n- `succeeded`: Number of items successfully created (status OK)\n- `failed`: Number of items that failed validation or processing (status NOK)\n- `results`: Per-item results preserving the original request order\n\n**Each results item contains:**\n- `listingIndex`: Zero-based index of this item in the original request list\n- `listingId`: As supplied in the request item, or `null` when it is missing or not a string\n- `status`: Processing result - `OK` (created successfully) or `NOK` (failed validation or processing)\n- `listing`: The listing as it now is (present for OK items, omitted for NOK items), see `GET /listings` for its fields\n- `errors`: Structured error details (present for NOK items, omitted for OK items)\n\n**Response HTTP status:**\n- 201: all items created successfully\n- 200: partial success (some OK, some NOK)\n- 401: missing or invalid token\n- 403: insufficient permissions\n- 409: a concurrent request wrote the same record first (`conflict_error`), retry the request\n- 422: all items failed","operationId":"postListingsBulkV2","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingBulkRequest"},"example":{"listings":[{"listingName":"Amsterdam Canal Apartment","areaId":"58ff0814-3aa1-5019-9afb-3cd9f398602c","url":"http://example.com/amsterdam-canal-apartment","address":{"thoroughfare":"Prinsengracht","locatorDesignatorNumber":263,"postCode":"1016GV","postName":"Amsterdam","fullAddress":"Prinsengracht 263, 1016GV Amsterdam"},"declaredAsShortTermRental":true,"registrationNumber":"REG0001"},{"listingName":"Rotterdam Harbor View","areaId":"974e2c23-b666-5044-a05c-9479a4c293a1","url":"http://example.com/rotterdam-harbor-view","address":{"thoroughfare":"Wilhelminakade","locatorDesignatorNumber":50,"postCode":"3072AP","postName":"Rotterdam","fullAddress":"Wilhelminakade 50, 3072AP Rotterdam"},"declaredAsShortTermRental":false},{"listingName":"Groningen Loft","areaId":"00000000-0000-0000-0000-000000000000","url":"http://example.com/groningen-loft","address":{"thoroughfare":"Herestraat","locatorDesignatorNumber":20,"postCode":"9711LA","postName":"Groningen","fullAddress":"Herestraat 20, 9711LA Groningen"},"declaredAsShortTermRental":true}]}}},"required":true},"responses":{"201":{"description":"All listings created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingBulkResponse"},"example":{"totalReceived":2,"succeeded":2,"failed":0,"results":[{"listingIndex":0,"listingId":"550e8400-e29b-41d4-a716-446655440000","status":"OK","listing":{"listingId":"550e8400-e29b-41d4-a716-446655440000","listingName":"Amsterdam Canal Apartment","status":"pending","flags":[],"areaId":"58ff0814-3aa1-5019-9afb-3cd9f398602c","areaName":"Amsterdam","competentAuthorityId":"c4ac8ccf-a281-5789-bad7-28dfac20ca7f","competentAuthorityName":"Amsterdam (inclusief Weesp)","url":"http://example.com/amsterdam-canal-apartment","address":{"thoroughfare":"Prinsengracht","locatorDesignatorNumber":263,"postCode":"1016GV","postName":"Amsterdam","fullAddress":"Prinsengracht 263, 1016GV Amsterdam"},"declaredAsShortTermRental":true,"registrationNumber":"REG0001","submittedAt":"2026-09-07T08:00:00Z","platformId":"8e70f1e2-4c61-477b-89b8-0dbf25ab8b21","platformName":"Test STR 01","createdAt":"2026-09-07T08:00:00Z"}},{"listingIndex":1,"listingId":null,"status":"OK","listing":{"listingId":"1d1a7f0c-2b4e-4a63-9c0f-7c1e5b2a9d10","listingName":"Rotterdam Harbor View","status":"pending","flags":[],"areaId":"974e2c23-b666-5044-a05c-9479a4c293a1","areaName":"Rotterdam","competentAuthorityId":"a30df3a7-7e38-534c-b9c0-7666bad077d2","competentAuthorityName":"Rotterdam","url":"http://example.com/rotterdam-harbor-view","address":{"thoroughfare":"Wilhelminakade","locatorDesignatorNumber":50,"postCode":"3072AP","postName":"Rotterdam","fullAddress":"Wilhelminakade 50, 3072AP Rotterdam"},"declaredAsShortTermRental":false,"submittedAt":"2026-09-07T08:00:00Z","platformId":"8e70f1e2-4c61-477b-89b8-0dbf25ab8b21","platformName":"Test STR 01","createdAt":"2026-09-07T08:00:00Z"}}]}}}},"500":{"description":"Internal Server Error - an unexpected issue occurred that prevented the request from being completed"},"503":{"description":"Service Unavailable - temporarily unable to process requests due to overload, maintenance, or dependency issues (database/authorization server)"},"200":{"description":"Partial success - some listings created, some failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingBulkResponse"},"example":{"totalReceived":4,"succeeded":1,"failed":3,"results":[{"listingIndex":0,"listingId":"550e8400-e29b-41d4-a716-446655440000","status":"OK","listing":{"listingId":"550e8400-e29b-41d4-a716-446655440000","listingName":"Amsterdam Canal Apartment","status":"pending","flags":[],"areaId":"58ff0814-3aa1-5019-9afb-3cd9f398602c","areaName":"Amsterdam","competentAuthorityId":"c4ac8ccf-a281-5789-bad7-28dfac20ca7f","competentAuthorityName":"Amsterdam (inclusief Weesp)","url":"http://example.com/amsterdam-canal-apartment","address":{"thoroughfare":"Prinsengracht","locatorDesignatorNumber":263,"postCode":"1016GV","postName":"Amsterdam","fullAddress":"Prinsengracht 263, 1016GV Amsterdam"},"declaredAsShortTermRental":true,"registrationNumber":"REG0001","submittedAt":"2026-09-07T08:00:00Z","platformId":"8e70f1e2-4c61-477b-89b8-0dbf25ab8b21","platformName":"Test STR 01","createdAt":"2026-09-07T08:00:00Z"}},{"listingIndex":1,"listingId":null,"status":"NOK","errors":{"detail":[{"msg":"Field required","type":"missing","loc":["declaredAsShortTermRental"]}]}},{"listingIndex":2,"listingId":"98f2c088-ce53-493a-a181-5a3a8e964f9b","status":"NOK","errors":{"detail":[{"msg":"Area with areaId '00000000-0000-0000-0000-000000000000' not found","type":"not_found_error","loc":["areaId"]}]}},{"listingIndex":3,"listingId":"82497bba-f6df-426f-9ea0-7b0c482f762f","status":"NOK","errors":{"detail":[{"msg":"Listing '82497bba-f6df-426f-9ea0-7b0c482f762f' is already screened (status 'flagged')","type":"conflict_error","loc":["listingId"]}]}}]}}}},"401":{"description":"Unauthorized - missing or invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - insufficient permissions"},"409":{"description":"Conflict - a concurrent request wrote the same record first (`conflict_error`), retry the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"All listings failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingBulkResponse"},"example":{"totalReceived":1,"succeeded":0,"failed":1,"results":[{"listingIndex":0,"listingId":"550e8400-e29b-41d4-a716-446655440000","status":"NOK","errors":{"detail":[{"msg":"Area with areaId '00000000-0000-0000-0000-000000000000' not found","type":"not_found_error","loc":["areaId"]}]}}]}}}}},"security":[{"OAuth2ClientCredentials":[]}]}},"/listings":{"get":{"tags":["str"],"summary":"Get the flagged listings of the currently authenticated platform","description":"Get the current listings of the currently authenticated platform that were flagged by the screening and not yet acknowledged (fixed scope: `status` is `flagged`, `acknowledgedAt` is null). Acknowledge them with `POST /listing-acknowledgements/bulk`. Returns at most 1000 listings per request (the default and maximum `limit`). Use the `offset` and `limit` pagination parameters to page through results. Optional filters use AND semantics: every provided filter narrows the result set. The `createdAtFrom` and `createdAtTo` form an inclusive `createdAt` range; the other filters are exact-match, except `flags` which matches any of the given codes.\n\n**Each listing contains:**\n- `listingId`: Functional ID identifying this listing\n- `listingName`: Display name (optional) of the listing\n- `status`: Lifecycle status: `pending`, `clear`, `flagged` or `acknowledged`\n- `flags`: Flag codes raised by the screening (`ABS`, `UNK`, `EXP`, `MIS`, `NPR`, `UNX`, `UDS`); empty until screened\n- `areaId`: Functional ID referencing the area where the listing is posted\n- `areaName`: Display name (optional) of the area\n- `competentAuthorityId`: Functional ID referencing the competent authority that owns the area\n- `competentAuthorityName`: Display name (optional) of the competent authority\n- `url`: URL referencing the listing online\n- `address`: Address composite (`thoroughfare`, `locatorDesignatorNumber` (optional), `locatorDesignatorLetter` (optional), `locatorDesignatorAddition` (optional), `postCode`, `postName`, `fullAddress`)\n- `declaredAsShortTermRental`: Host self-declaration\n- `registrationNumber`: Registration number shown on the listing (optional)\n- `submittedAt`: Timestamp of the platform's submission (UTC)\n- `screenedAt`: Timestamp of the screening (UTC, null until screened)\n- `acknowledgedAt`: Timestamp of the acknowledgement (UTC, null until acknowledged)\n- `platformId`: Functional ID referencing the platform that submitted the listing\n- `platformName`: Display name (optional) of the platform\n- `createdAt`: Timestamp when this listing version was created (UTC); the version token for screening and acknowledgement","operationId":"getListingsV2","security":[{"OAuth2ClientCredentials":[]}],"parameters":[{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Number of records to skip (default: 0)","default":0,"title":"Offset"},"description":"Number of records to skip (default: 0)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"description":"Maximum number of records to return (default: 1000, max: 1000)","default":1000,"title":"Limit"},"description":"Maximum number of records to return (default: 1000, max: 1000)"},{"name":"createdAtFrom","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Filter listings whose createdAt timestamp is greater than or equal to this UTC value","examples":["2026-09-01T00:00:00Z"],"title":"Createdatfrom"},"description":"Filter listings whose createdAt timestamp is greater than or equal to this UTC value"},{"name":"createdAtTo","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Filter listings whose createdAt timestamp is less than or equal to this UTC value","examples":["2026-09-30T23:59:59Z"],"title":"Createdatto"},"description":"Filter listings whose createdAt timestamp is less than or equal to this UTC value"},{"name":"areaId","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":64,"pattern":"^[A-Za-z0-9-]+$"},{"type":"null"}],"description":"Filter by area functional ID","examples":["58ff0814-3aa1-5019-9afb-3cd9f398602c"],"title":"Areaid"},"description":"Filter by area functional ID"},{"name":"competentAuthorityId","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":64,"pattern":"^[A-Za-z0-9-]+$"},{"type":"null"}],"description":"Filter by competent authority functional ID","examples":["c4ac8ccf-a281-5789-bad7-28dfac20ca7f"],"title":"Competentauthorityid"},"description":"Filter by competent authority functional ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingListResponse"},"example":{"listings":[{"listingId":"550e8400-e29b-41d4-a716-446655440000","listingName":"Amsterdam Canal Apartment","status":"flagged","flags":["UNK"],"areaId":"58ff0814-3aa1-5019-9afb-3cd9f398602c","areaName":"Amsterdam","competentAuthorityId":"c4ac8ccf-a281-5789-bad7-28dfac20ca7f","competentAuthorityName":"Amsterdam (inclusief Weesp)","url":"http://example.com/amsterdam-canal-apartment","address":{"thoroughfare":"Prinsengracht","locatorDesignatorNumber":263,"postCode":"1016GV","postName":"Amsterdam","fullAddress":"Prinsengracht 263, 1016GV Amsterdam"},"declaredAsShortTermRental":true,"registrationNumber":"REG0001","submittedAt":"2026-09-07T08:00:00Z","screenedAt":"2026-09-08T06:00:00Z","platformId":"8e70f1e2-4c61-477b-89b8-0dbf25ab8b21","platformName":"Test STR 01","createdAt":"2026-09-08T06:00:00Z"}]}}}},"500":{"description":"Internal Server Error - an unexpected issue occurred that prevented the request from being completed"},"503":{"description":"Service Unavailable - temporarily unable to process requests due to overload, maintenance, or dependency issues (database/authorization server)"},"400":{"description":"Bad request - invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized - missing or invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - insufficient permissions"}}}},"/listings/count":{"get":{"tags":["str"],"summary":"Get the count of flagged listings of the currently authenticated platform (optional, to support pagination)","description":"Get the count of the current flagged listings of the currently authenticated platform (optional, to support pagination). Optional filters use AND semantics: every provided filter narrows the result set. The `createdAtFrom` and `createdAtTo` form an inclusive `createdAt` range; the other filters are exact-match, except `flags` which matches any of the given codes.","operationId":"countListingsV2","security":[{"OAuth2ClientCredentials":[]}],"parameters":[{"name":"createdAtFrom","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Filter listings whose createdAt timestamp is greater than or equal to this UTC value","examples":["2026-09-01T00:00:00Z"],"title":"Createdatfrom"},"description":"Filter listings whose createdAt timestamp is greater than or equal to this UTC value"},{"name":"createdAtTo","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Filter listings whose createdAt timestamp is less than or equal to this UTC value","examples":["2026-09-30T23:59:59Z"],"title":"Createdatto"},"description":"Filter listings whose createdAt timestamp is less than or equal to this UTC value"},{"name":"areaId","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":64,"pattern":"^[A-Za-z0-9-]+$"},{"type":"null"}],"description":"Filter by area functional ID","examples":["58ff0814-3aa1-5019-9afb-3cd9f398602c"],"title":"Areaid"},"description":"Filter by area functional ID"},{"name":"competentAuthorityId","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":64,"pattern":"^[A-Za-z0-9-]+$"},{"type":"null"}],"description":"Filter by competent authority functional ID","examples":["c4ac8ccf-a281-5789-bad7-28dfac20ca7f"],"title":"Competentauthorityid"},"description":"Filter by competent authority functional ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingCountResponse"}}}},"500":{"description":"Internal Server Error - an unexpected issue occurred that prevented the request from being completed"},"503":{"description":"Service Unavailable - temporarily unable to process requests due to overload, maintenance, or dependency issues (database/authorization server)"},"400":{"description":"Bad request - invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized - missing or invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - insufficient permissions"}}}},"/listing-acknowledgements/bulk":{"post":{"tags":["str"],"summary":"Acknowledge flagged listings in bulk for the currently authenticated platform","description":"Acknowledge 1-1000 flagged listings (= random check performed). Each acknowledged listing becomes a new `acknowledged` version; its flags are retained. The acknowledgement carries no further data.\n\n**Concurrency:**\n- `createdAt` is the `createdAt` of the flagged version, as returned by `GET /listings`\n- When that version is no longer current (for example, the listing was re-screened), the item is marked NOK with `conflict_error` and `loc` `[\"createdAt\"]`; the listing then reappears in `GET /listings` with its new version\n- A retried acknowledgement fails the same way: treat it as \"already acknowledged\"\n\n**Validation flow (4 steps):**\n\n1. **Syntax and semantical validation** - each item is validated individually.\n2. **Referential Integrity Check** - the listing must exist for the currently authenticated platform (`not_found_error`).\n3. **Versioning and Bulk Insert** - the current version is locked and checked (`createdAt` current, status `flagged`), marked ended, and the `acknowledged` versions are inserted in a single multi-row INSERT.\n4. **Feedback** - per-item OK/NOK response preserving original order.\n\n**Intra-batch duplicates (last-wins):**\nWhen the same `listingId` appears multiple times in a single batch, only the last\noccurrence is processed. Earlier occurrences receive NOK.\n\n**The request contains:**\n- `acknowledgements`: Array of acknowledgements to process (1-1000 items per batch)\n\n**Each acknowledgement item in the request contains:**\n- `listingId`: Functional ID of the flagged listing\n- `createdAt`: `createdAt` of the flagged listing version (UTC)\n\n**The response contains:**\n- `totalReceived`, `succeeded`, `failed`: Summary counts\n- `results`: Per-item results preserving the original request order (`listingIndex`, `listingId`, `status`, `listing` for OK items, `errors` for NOK items)\n\n**Response HTTP status:**\n- 201: all items acknowledged\n- 200: partial success (some OK, some NOK)\n- 401: missing or invalid token\n- 403: insufficient permissions\n- 409: a concurrent request wrote the same record first (`conflict_error`), retry the request\n- 422: all items failed","operationId":"postListingAcknowledgementsBulkV2","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingAcknowledgementBulkRequest"},"example":{"acknowledgements":[{"listingId":"550e8400-e29b-41d4-a716-446655440000","createdAt":"2026-09-08T06:00:00Z"}]}}},"required":true},"responses":{"201":{"description":"All listings acknowledged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingAcknowledgementBulkResponse"},"example":{"totalReceived":1,"succeeded":1,"failed":0,"results":[{"listingIndex":0,"listingId":"550e8400-e29b-41d4-a716-446655440000","status":"OK","listing":{"listingId":"550e8400-e29b-41d4-a716-446655440000","listingName":"Amsterdam Canal Apartment","status":"acknowledged","flags":["UNK"],"areaId":"58ff0814-3aa1-5019-9afb-3cd9f398602c","areaName":"Amsterdam","competentAuthorityId":"c4ac8ccf-a281-5789-bad7-28dfac20ca7f","competentAuthorityName":"Amsterdam (inclusief Weesp)","url":"http://example.com/amsterdam-canal-apartment","address":{"thoroughfare":"Prinsengracht","locatorDesignatorNumber":263,"postCode":"1016GV","postName":"Amsterdam","fullAddress":"Prinsengracht 263, 1016GV Amsterdam"},"declaredAsShortTermRental":true,"registrationNumber":"REG0001","submittedAt":"2026-09-07T08:00:00Z","screenedAt":"2026-09-08T06:00:00Z","acknowledgedAt":"2026-09-09T10:00:00Z","platformId":"8e70f1e2-4c61-477b-89b8-0dbf25ab8b21","platformName":"Test STR 01","createdAt":"2026-09-09T10:00:00Z"}}]}}}},"500":{"description":"Internal Server Error - an unexpected issue occurred that prevented the request from being completed"},"503":{"description":"Service Unavailable - temporarily unable to process requests due to overload, maintenance, or dependency issues (database/authorization server)"},"200":{"description":"Partial success - some listings acknowledged, some failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingAcknowledgementBulkResponse"},"example":{"totalReceived":3,"succeeded":1,"failed":2,"results":[{"listingIndex":0,"listingId":"550e8400-e29b-41d4-a716-446655440000","status":"OK","listing":{"listingId":"550e8400-e29b-41d4-a716-446655440000","listingName":"Amsterdam Canal Apartment","status":"acknowledged","flags":["UNK"],"areaId":"58ff0814-3aa1-5019-9afb-3cd9f398602c","areaName":"Amsterdam","competentAuthorityId":"c4ac8ccf-a281-5789-bad7-28dfac20ca7f","competentAuthorityName":"Amsterdam (inclusief Weesp)","url":"http://example.com/amsterdam-canal-apartment","address":{"thoroughfare":"Prinsengracht","locatorDesignatorNumber":263,"postCode":"1016GV","postName":"Amsterdam","fullAddress":"Prinsengracht 263, 1016GV Amsterdam"},"declaredAsShortTermRental":true,"registrationNumber":"REG0001","submittedAt":"2026-09-07T08:00:00Z","screenedAt":"2026-09-08T06:00:00Z","acknowledgedAt":"2026-09-09T10:00:00Z","platformId":"8e70f1e2-4c61-477b-89b8-0dbf25ab8b21","platformName":"Test STR 01","createdAt":"2026-09-09T10:00:00Z"}},{"listingIndex":1,"listingId":"abc-123","status":"NOK","errors":{"detail":[{"msg":"Listing 'abc-123' version '2026-09-07T08:00:00Z' is no longer current","type":"conflict_error","loc":["createdAt"]}]}},{"listingIndex":2,"listingId":"unknown-id","status":"NOK","errors":{"detail":[{"msg":"Listing 'unknown-id' not found","type":"not_found_error","loc":["listingId"]}]}}]}}}},"401":{"description":"Unauthorized - missing or invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - insufficient permissions"},"409":{"description":"Conflict - a concurrent request wrote the same record first (`conflict_error`), retry the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"All acknowledgements failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingAcknowledgementBulkResponse"},"example":{"totalReceived":1,"succeeded":0,"failed":1,"results":[{"listingIndex":0,"listingId":"abc-123","status":"NOK","errors":{"detail":[{"msg":"Listing 'abc-123' version '2026-09-07T08:00:00Z' is no longer current","type":"conflict_error","loc":["createdAt"]}]}}]}}}}},"security":[{"OAuth2ClientCredentials":[]}]}}},"components":{"schemas":{"ActivityBulkRequest":{"properties":{"activities":{"items":{"$ref":"#/components/schemas/ActivityRequest"},"type":"array","maxItems":1000,"minItems":1,"title":"Activities","description":"Array of activity objects to process (1-1000 items per batch)"}},"type":"object","required":["activities"],"title":"Activity.BulkRequest","description":"Bulk activity request schema.\n\nThe `activities` field is typed as `list[ActivityRequest]` for the OpenAPI\ncontract, but item-level validation is skipped at request-parse time (via\n`SkipValidation`). This preserves the Application-First Validation flow:\neach item is validated individually in the service layer, so one invalid\nitem is marked NOK without failing the whole batch."},"ActivityBulkResponse":{"properties":{"totalReceived":{"type":"integer","minimum":0.0,"title":"Totalreceived","description":"Total number of items received in the request","examples":[2]},"succeeded":{"type":"integer","minimum":0.0,"title":"Succeeded","description":"Number of items successfully created (status OK)","examples":[2]},"failed":{"type":"integer","minimum":0.0,"title":"Failed","description":"Number of items that failed validation or processing (status NOK)","examples":[0]},"results":{"items":{"$ref":"#/components/schemas/ActivityBulkResultItem"},"type":"array","title":"Results","description":"Per-item results preserving the original request order","example":[{"activity":{"activityId":"550e8400-e29b-41d4-a716-446655440000","address":{"fullAddress":"Prinsengracht 263, 1016GV Amsterdam","locatorDesignatorNumber":263,"postCode":"1016GV","postName":"Amsterdam","thoroughfare":"Prinsengracht"},"areaId":"58ff0814-3aa1-5019-9afb-3cd9f398602c","competentAuthorityId":"c4ac8ccf-a281-5789-bad7-28dfac20ca7f","competentAuthorityName":"Gemeente Amsterdam","countryOfGuests":["NLD","DEU","BEL","N/A"],"createdAt":"2025-06-01T12:00:00Z","numberOfGuests":4,"platformId":"8e70f1e2-4c61-477b-89b8-0dbf25ab8b21","platformName":"Test STR 01","registrationNumber":"REG0001","status":"finished","temporal":{"endDatetime":"2025-06-07T11:00:00Z","startDatetime":"2025-06-01T14:00:00Z"},"url":"http://example.com/amsterdam-myhouse-1"},"activityId":"550e8400-e29b-41d4-a716-446655440000","activityIndex":0,"status":"OK"},{"activityId":null,"activityIndex":1,"errors":{"detail":[{"loc":["areaId"],"msg":"Area with areaId 'c5f54e98-226a-411b-b015-ca13070c6dc5' not found","type":"not_found_error"}]},"status":"NOK"}]}},"type":"object","required":["totalReceived","succeeded","failed","results"],"title":"Activity.BulkResponse","description":"Bulk activity response schema.\n\nReturns per-item OK/NOK feedback with summary counts.\nValidation flow Step 4: the original list enriched with status and error_message."},"ActivityBulkResultItem":{"properties":{"activityIndex":{"type":"integer","minimum":0.0,"title":"Activityindex","description":"Zero-based index of this item in the original request list","examples":[0]},"activityId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Activityid","description":"As supplied in the request item, or `null` when it is missing or not a string","examples":["550e8400-e29b-41d4-a716-446655440000"]},"status":{"type":"string","enum":["OK","NOK"],"title":"Status","description":"Processing result - `OK` (created successfully) or `NOK` (failed validation or processing)","examples":["OK"]},"activity":{"anyOf":[{"$ref":"#/components/schemas/ActivityResponse"},{"type":"null"}],"description":"The full activity object (present for OK items, omitted for NOK items)"},"errors":{"anyOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"null"}],"description":"Structured error details (present for NOK items, omitted for OK items)","examples":[{"detail":[{"loc":["areaId"],"msg":"Area with areaId 'unknown-id' not found","type":"not_found_error"}]}]}},"type":"object","required":["activityIndex","status"],"title":"Activity.BulkResultItem","description":"Result for a single item in a bulk activity response."},"ActivityRequest":{"properties":{"activityId":{"anyOf":[{"type":"string","maxLength":64,"minLength":1,"pattern":"^[A-Za-z0-9-]+$"},{"type":"null"}],"title":"Activityid","description":"Functional ID identifying the activity (alphanumeric with hyphens `^[A-Za-z0-9\\-]+$`, max 64 chars, optionally supplied, auto-generated as deterministic UUIDv8 RFC 9562 if not supplied)","examples":["550e8400-e29b-41d4-a716-446655440000"]},"activityName":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Activityname","description":"Display name of the activity (optional, max 64 chars)","examples":["Amsterdam Summer Rental"]},"status":{"$ref":"#/components/schemas/ActivityStatus","description":"Lifecycle status of the activity. Defaults to `finished` when omitted; may also be `cancelled`.","default":"finished","examples":["finished","cancelled"]},"areaId":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[A-Za-z0-9-]+$","title":"Areaid","description":"Functional ID referencing the area where the activity took place (case-sensitive)","examples":["58ff0814-3aa1-5019-9afb-3cd9f398602c","58FF0814-3AA1-5019-9AFB-3CD9F398602C"]},"url":{"type":"string","maxLength":2048,"minLength":1,"title":"Url","description":"URL of the originating listing/advertisement (max 2048 chars)","examples":["http://example.com/amsterdam-myhouse-1"]},"address":{"$ref":"#/components/schemas/CommonAddressRequest","description":"Address composite (`thoroughfare`, `locatorDesignatorNumber` (optional), `locatorDesignatorLetter` (optional), `locatorDesignatorAddition` (optional), `postCode`, `postName`, `fullAddress`)"},"registrationNumber":{"type":"string","maxLength":128,"minLength":1,"title":"Registrationnumber","description":"Registration number of the address (max 128 chars)","examples":["REG0001"]},"numberOfGuests":{"type":"integer","maximum":1024.0,"minimum":1.0,"title":"Numberofguests","description":"Number of guests (1-1024)","examples":[4]},"countryOfGuests":{"items":{"type":"string"},"type":"array","maxItems":1024,"minItems":1,"title":"Countryofguests","description":"Array of country codes of guests (1-1024; each element is ISO 3166-1 alpha-3 or 'N/A', uppercase only). Length must equal numberOfGuests.","examples":[["NLD","NLD","DEU","BEL"]]},"temporal":{"$ref":"#/components/schemas/CommonTemporalRequest","description":"Temporal composite (`startDatetime`, `endDatetime`), both in UTC with offset `Z` or `+00:00`"}},"type":"object","required":["areaId","url","address","registrationNumber","numberOfGuests","countryOfGuests","temporal"],"title":"Activity.Request","description":"Activity request schema for creating rental activities.\n\nActivity ID:\n- Optional: If not provided, will be auto-generated (RFC 9562 UUID)\n\nActivity Name:\n- Optional: Display name (max 64 chars)\n\nValidation Layer:\n- Validates all syntax constraints (lengths, ranges, types)\n\nConstraints (enforced at database level):\n- Unique constraint: (activityId, platformId, createdAt) for versioning support"},"ActivityResponse":{"properties":{"activityId":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[A-Za-z0-9-]+$","title":"Activityid","description":"Functional ID identifying this activity","examples":["550e8400-e29b-41d4-a716-446655440000"]},"activityName":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Activityname","description":"Display name (optional) of the activity"},"status":{"$ref":"#/components/schemas/ActivityStatus","description":"Lifecycle status of the activity: `finished` or `cancelled`.","examples":["finished","cancelled"]},"areaId":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[A-Za-z0-9-]+$","title":"Areaid","description":"Functional ID referencing the area where this activity took place (case-sensitive)","examples":["58ff0814-3aa1-5019-9afb-3cd9f398602c","58FF0814-3AA1-5019-9AFB-3CD9F398602C"]},"areaName":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Areaname","description":"Display name (optional) of the area where this activity took place"},"competentAuthorityId":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[A-Za-z0-9-]+$","title":"Competentauthorityid","description":"Functional ID referencing the competent authority that owns the area","examples":["c4ac8ccf-a281-5789-bad7-28dfac20ca7f","a30df3a7-7e38-534c-b9c0-7666bad077d2"]},"competentAuthorityName":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Competentauthorityname","description":"Display name (optional) of the competent authority"},"url":{"type":"string","maxLength":2048,"title":"Url","description":"URL of the originating listing/advertisement (max 2048 chars)"},"address":{"$ref":"#/components/schemas/CommonAddressResponse","description":"Address composite (`thoroughfare`, `locatorDesignatorNumber` (optional), `locatorDesignatorLetter` (optional), `locatorDesignatorAddition` (optional), `postCode`, `postName`, `fullAddress`)"},"registrationNumber":{"type":"string","maxLength":128,"title":"Registrationnumber","description":"Registration number of the address (max 128 chars)"},"numberOfGuests":{"type":"integer","maximum":1024.0,"minimum":1.0,"title":"Numberofguests","description":"Number of guests (1-1024)"},"countryOfGuests":{"items":{"type":"string"},"type":"array","maxItems":1024,"minItems":1,"title":"Countryofguests","description":"Array of country codes of guests (1-1024; each element is ISO 3166-1 alpha-3 or 'N/A'); array length equals numberOfGuests."},"temporal":{"$ref":"#/components/schemas/CommonTemporalResponse","description":"Temporal composite (`startDatetime`, `endDatetime`)"},"platformId":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[A-Za-z0-9-]+$","title":"Platformid","description":"Functional ID referencing the platform that owns the activity","examples":["8e70f1e2-4c61-477b-89b8-0dbf25ab8b21","227e07d4-37c4-4ceb-aa16-80346d258f6b"]},"platformName":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Platformname","description":"Display name (optional) of the platform"},"createdAt":{"type":"string","format":"date-time","title":"Createdat","description":"Timestamp when this activity version was created (UTC)"}},"type":"object","required":["activityId","status","areaId","competentAuthorityId","url","address","registrationNumber","numberOfGuests","countryOfGuests","temporal","platformId","createdAt"],"title":"Activity.Response","description":"Activity response schema."},"ActivityStatus":{"type":"string","enum":["finished","cancelled"],"title":"Activity.Status","description":"Lifecycle status for an activity record."},"AreaCountResponse":{"properties":{"count":{"type":"integer","minimum":0.0,"title":"Count","description":"Total number of areas in context of the current SDEP/member state","examples":[42]}},"type":"object","required":["count"],"title":"Area.CountResponse","description":"Count of areas response schema."},"AreaListResponse":{"properties":{"areas":{"items":{"$ref":"#/components/schemas/AreaResponse"},"type":"array","title":"Areas","description":"List of areas in context of the current SDEP/member state"}},"type":"object","required":["areas"],"title":"Area.ListResponse","description":"List of areas response schema."},"AreaResponse":{"properties":{"areaId":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[A-Za-z0-9-]+$","title":"Areaid","description":"Functional ID identifying this area","examples":["58ff0814-3aa1-5019-9afb-3cd9f398602c"]},"areaName":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Areaname","description":"Display name (optional) of the area","examples":["Amsterdam"]},"regulation":{"$ref":"#/components/schemas/Regulation","description":"Regulation type of the area - 'listing', 'activity', or 'all'","default":"all","examples":["all"]},"filename":{"type":"string","maxLength":64,"title":"Filename","description":"Name of the area shapefile (e.g., 'area.zip')","examples":["Amsterdam.zip"]},"competentAuthorityId":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[A-Za-z0-9-]+$","title":"Competentauthorityid","description":"Functional ID of the competent authority that owns the area","examples":["c4ac8ccf-a281-5789-bad7-28dfac20ca7f"]},"competentAuthorityName":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Competentauthorityname","description":"Display name (optional) of the competent authority","examples":["Amsterdam (inclusief Weesp)"]},"createdAt":{"type":"string","format":"date-time","title":"Createdat","description":"Timestamp when this area version was created (UTC)","examples":["2025-01-01T00:00:00Z"]}},"type":"object","required":["areaId","filename","competentAuthorityId","createdAt"],"title":"Area.Response","description":"Area response schema."},"CommonAddressRequest":{"properties":{"thoroughfare":{"type":"string","maxLength":80,"title":"Thoroughfare","description":"Street / public space name","examples":["Prinsengracht"]},"locatorDesignatorNumber":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Locatordesignatornumber","description":"Numeric house number component (optional, >= 0 when provided)","examples":[263]},"locatorDesignatorLetter":{"anyOf":[{"type":"string","maxLength":10},{"type":"null"}],"title":"Locatordesignatorletter","description":"Letter/character suffix (optional, e.g. 'a', 'bis', 'ter')","examples":["a"]},"locatorDesignatorAddition":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Locatordesignatoraddition","description":"Additional qualifier (optional, e.g. 'II', 'Apt 3')","examples":["II"]},"postCode":{"type":"string","maxLength":10,"minLength":1,"pattern":"^[0-9A-Za-z]+$","title":"Postcode","description":"Postal code (no spaces, alphanumeric)","examples":["1016GV"]},"postName":{"type":"string","maxLength":80,"title":"Postname","description":"City / town / village","examples":["Amsterdam"]},"fullAddress":{"type":"string","maxLength":328,"title":"Fulladdress","description":"Full address as a single string (required, max 328 chars)","examples":["Turfmarkt 147a-5h, 2500EA Den Haag"]}},"type":"object","required":["thoroughfare","postCode","postName","fullAddress"],"title":"Common.AddressRequest","description":"Address composite schema for activity requests (INSPIRE/STR-AP field names).\n\nValidation Layer:\n- All syntax validation (lengths, types, constraints) happens here\n- Service layer receives validated data"},"CommonAddressResponse":{"properties":{"thoroughfare":{"type":"string","maxLength":80,"title":"Thoroughfare","description":"Street / public space name (max 80 chars)"},"locatorDesignatorNumber":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Locatordesignatornumber","description":"Numeric house number component (optional, >= 0 when provided)"},"locatorDesignatorLetter":{"anyOf":[{"type":"string","maxLength":10},{"type":"null"}],"title":"Locatordesignatorletter","description":"Letter/character suffix (optional, max 10 chars)"},"locatorDesignatorAddition":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Locatordesignatoraddition","description":"Additional qualifier (optional, max 128 chars)"},"postCode":{"type":"string","maxLength":10,"title":"Postcode","description":"Postal code (max 10 chars)"},"postName":{"type":"string","maxLength":80,"title":"Postname","description":"City / town / village (max 80 chars)"},"fullAddress":{"type":"string","maxLength":328,"title":"Fulladdress","description":"Full address as a single string (max 328 chars)"}},"type":"object","required":["thoroughfare","postCode","postName","fullAddress"],"title":"Common.AddressResponse","description":"Address composite schema for activity responses (INSPIRE/STR-AP field names)."},"Regulation":{"type":"string","enum":["listing","activity","all"],"title":"Common.Regulation","description":"Regulation type for an area: 'listing', 'activity', or 'all' (covers both)."},"CommonTemporalRequest":{"properties":{"startDatetime":{"type":"string","format":"date-time","title":"Startdatetime","description":"Start date and time of the rental activity, in UTC with offset `Z` or `+00:00` (year must be >= 2025)","examples":["2025-06-01T14:00:00Z"]},"endDatetime":{"type":"string","format":"date-time","title":"Enddatetime","description":"End date and time of the rental activity, in UTC with offset `Z` or `+00:00` (must be after startDatetime)","examples":["2025-06-07T11:00:00Z"]}},"type":"object","required":["startDatetime","endDatetime"],"title":"Common.TemporalRequest","description":"Temporal composite schema for activity requests.\n\nValidation Layer:\n- Both timestamps must carry the UTC offset `Z` or `+00:00`\n- Other offsets, no offset and date-only values are rejected\n- Ensures start year is >= 2025\n- Ensures start is before end"},"CommonTemporalResponse":{"properties":{"startDatetime":{"type":"string","format":"date-time","title":"Startdatetime","description":"Start date and time of the rental activity"},"endDatetime":{"type":"string","format":"date-time","title":"Enddatetime","description":"End date and time of the rental activity"}},"type":"object","required":["startDatetime","endDatetime"],"title":"Common.TemporalResponse","description":"Temporal composite schema for activity responses."},"ErrorDetail":{"properties":{"msg":{"type":"string","title":"Msg","description":"Human-readable error message"},"type":{"type":"string","title":"Type","description":"Error type identifier"},"loc":{"anyOf":[{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array"},{"type":"null"}],"title":"Loc","description":"Location of the error (e.g. ['body', 'fieldName'])"}},"type":"object","required":["msg","type"],"title":"Error.Detail","description":"Detail of a single error."},"ErrorResponse":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ErrorDetail"},"type":"array","title":"Detail","description":"List of error details"}},"type":"object","required":["detail"],"title":"Error.Response","description":"Standardized error response format."},"ListingBulkRequest":{"properties":{"listings":{"items":{"$ref":"#/components/schemas/ListingRequest"},"type":"array","maxItems":1000,"minItems":1,"title":"Listings","description":"Array of listing objects to process (1-1000 items per batch)"}},"type":"object","required":["listings"],"title":"Listing.BulkRequest","description":"Bulk listing request schema (`POST /listings/bulk`)."},"ListingBulkResponse":{"properties":{"totalReceived":{"type":"integer","minimum":0.0,"title":"Totalreceived","description":"Total number of items received in the request","examples":[2]},"succeeded":{"type":"integer","minimum":0.0,"title":"Succeeded","description":"Number of items successfully processed (status OK)","examples":[2]},"failed":{"type":"integer","minimum":0.0,"title":"Failed","description":"Number of items that failed validation or processing (status NOK)","examples":[0]},"results":{"items":{"$ref":"#/components/schemas/ListingBulkResultItem"},"type":"array","title":"Results","description":"Per-item results preserving the original request order"}},"type":"object","required":["totalReceived","succeeded","failed","results"],"title":"Listing.BulkResponse","description":"Bulk listing response schema: per-item OK/NOK feedback with summary counts."},"ListingBulkResultItem":{"properties":{"listingIndex":{"type":"integer","minimum":0.0,"title":"Listingindex","description":"Zero-based index of this item in the original request list","examples":[0]},"listingId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Listingid","description":"As supplied in the request item, or `null` when it is missing or not a string","examples":["550e8400-e29b-41d4-a716-446655440000"]},"status":{"type":"string","enum":["OK","NOK"],"title":"Status","description":"Processing result - `OK` (new listing version created) or `NOK` (failed validation or processing)","examples":["OK"]},"listing":{"anyOf":[{"$ref":"#/components/schemas/ListingResponse"},{"type":"null"}],"description":"The listing as it now is (present for OK items, omitted for NOK items)"},"errors":{"anyOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"null"}],"description":"Structured error details (present for NOK items, omitted for OK items)","examples":[{"detail":[{"loc":["createdAt"],"msg":"Listing 'abc-123' version '2026-09-07T08:00:00Z' is no longer current","type":"conflict_error"}]}]}},"type":"object","required":["listingIndex","status"],"title":"Listing.BulkResultItem","description":"Result for a single item in a listing bulk response."},"ListingCountResponse":{"properties":{"count":{"type":"integer","minimum":0.0,"title":"Count","description":"Total number of listing records","examples":[42]}},"type":"object","required":["count"],"title":"Listing.CountResponse","description":"Count of listings response schema."},"ListingFlag":{"type":"string","enum":["ABS","UNK","EXP","MIS","NPR","UNX","UDS"],"title":"Listing.Flag","description":"Flag code raised by listing screening, see docs/LISTING_FUNC.md."},"ListingListResponse":{"properties":{"listings":{"items":{"$ref":"#/components/schemas/ListingResponse"},"type":"array","title":"Listings","description":"List of listings"}},"type":"object","required":["listings"],"title":"Listing.ListResponse","description":"List of listings for GET responses."},"ListingRequest":{"properties":{"listingId":{"anyOf":[{"type":"string","maxLength":64,"minLength":1,"pattern":"^[A-Za-z0-9-]+$"},{"type":"null"}],"title":"Listingid","description":"Functional ID identifying the listing (alphanumeric with hyphens `^[A-Za-z0-9\\-]+$`, max 64 chars, optionally supplied, auto-generated as deterministic UUIDv8 RFC 9562 if not supplied). Resubmitting an ID with other content corrects the listing while it is `pending`.","examples":["550e8400-e29b-41d4-a716-446655440000"]},"listingName":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Listingname","description":"Display name of the listing (optional, max 64 chars)","examples":["Amsterdam Canal Apartment"]},"areaId":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[A-Za-z0-9-]+$","title":"Areaid","description":"Functional ID referencing the area where the listing is posted (case-sensitive)","examples":["58ff0814-3aa1-5019-9afb-3cd9f398602c","974e2c23-b666-5044-a05c-9479a4c293a1"]},"url":{"type":"string","maxLength":2048,"minLength":1,"title":"Url","description":"URL referencing the listing online (max 2048 chars)","examples":["http://example.com/amsterdam-canal-apartment"]},"address":{"$ref":"#/components/schemas/CommonAddressRequest","description":"Address composite (`thoroughfare`, `locatorDesignatorNumber` (optional), `locatorDesignatorLetter` (optional), `locatorDesignatorAddition` (optional), `postCode`, `postName`, `fullAddress`)"},"declaredAsShortTermRental":{"type":"boolean","title":"Declaredasshorttermrental","description":"Host self-declaration: `true` when the host declared the listing as a short-term rental","examples":[true]},"registrationNumber":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"Registrationnumber","description":"Registration number shown on the listing (optional, max 128 chars)","examples":["REG0001"]}},"type":"object","required":["areaId","url","address","declaredAsShortTermRental"],"title":"Listing.Request","description":"Listing request schema, submitted by a platform (`POST /listings/bulk`).\n\nListing ID:\n- Optional: If not provided, will be auto-generated (RFC 9562 UUID)\n- Resubmitting the same ID with other content corrects the listing while it\n  is `pending`; the same content returns the stored listing\n\nConstraints (enforced at database level):\n- Unique constraint: (listingId, platformId, createdAt) for versioning support"},"ListingResponse":{"properties":{"listingId":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[A-Za-z0-9-]+$","title":"Listingid","description":"Functional ID identifying this listing","examples":["550e8400-e29b-41d4-a716-446655440000"]},"listingName":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Listingname","description":"Display name (optional) of the listing"},"status":{"$ref":"#/components/schemas/ListingStatus","description":"Lifecycle status: `pending`, `clear`, `flagged` or `acknowledged`","examples":["flagged"]},"flags":{"items":{"$ref":"#/components/schemas/ListingFlag"},"type":"array","title":"Flags","description":"Flag codes raised by the screening (empty until screened; non-empty when `flagged` or `acknowledged`)","examples":[["UNK"]]},"areaId":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[A-Za-z0-9-]+$","title":"Areaid","description":"Functional ID referencing the area where the listing is posted (case-sensitive)","examples":["58ff0814-3aa1-5019-9afb-3cd9f398602c"]},"areaName":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Areaname","description":"Display name (optional) of the area"},"competentAuthorityId":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[A-Za-z0-9-]+$","title":"Competentauthorityid","description":"Functional ID referencing the competent authority that owns the area","examples":["c4ac8ccf-a281-5789-bad7-28dfac20ca7f"]},"competentAuthorityName":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Competentauthorityname","description":"Display name (optional) of the competent authority"},"url":{"type":"string","maxLength":2048,"title":"Url","description":"URL referencing the listing online (max 2048 chars)"},"address":{"$ref":"#/components/schemas/CommonAddressResponse","description":"Address composite (`thoroughfare`, `locatorDesignatorNumber` (optional), `locatorDesignatorLetter` (optional), `locatorDesignatorAddition` (optional), `postCode`, `postName`, `fullAddress`)"},"declaredAsShortTermRental":{"type":"boolean","title":"Declaredasshorttermrental","description":"Host self-declaration: `true` when the host declared the listing as a short-term rental"},"registrationNumber":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Registrationnumber","description":"Registration number shown on the listing (optional, max 128 chars)"},"submittedAt":{"type":"string","format":"date-time","title":"Submittedat","description":"Timestamp of the platform's submission (UTC); unchanged by screening and acknowledgement"},"screenedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Screenedat","description":"Timestamp of the screening (UTC); null until screened"},"acknowledgedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Acknowledgedat","description":"Timestamp of the acknowledgement (UTC); null until acknowledged"},"platformId":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[A-Za-z0-9-]+$","title":"Platformid","description":"Functional ID referencing the platform that submitted the listing","examples":["8e70f1e2-4c61-477b-89b8-0dbf25ab8b21"]},"platformName":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Platformname","description":"Display name (optional) of the platform"},"createdAt":{"type":"string","format":"date-time","title":"Createdat","description":"Timestamp when this listing version was created (UTC); the version token for screening and acknowledgement"}},"type":"object","required":["listingId","status","flags","areaId","competentAuthorityId","url","address","declaredAsShortTermRental","submittedAt","platformId","createdAt"],"title":"Listing.Response","description":"Listing response schema, the same for every audience."},"ListingStatus":{"type":"string","enum":["pending","clear","flagged","acknowledged"],"title":"Listing.Status","description":"Lifecycle status for a listing (random check) record."},"ListingAcknowledgementBulkRequest":{"properties":{"acknowledgements":{"items":{"$ref":"#/components/schemas/ListingAcknowledgementRequest"},"type":"array","maxItems":1000,"minItems":1,"title":"Acknowledgements","description":"Array of acknowledgements to process (1-1000 items per batch)"}},"type":"object","required":["acknowledgements"],"title":"ListingAcknowledgement.BulkRequest","description":"Bulk acknowledgement request schema (`POST /listing-acknowledgements/bulk`)."},"ListingAcknowledgementBulkResponse":{"properties":{"totalReceived":{"type":"integer","minimum":0.0,"title":"Totalreceived","description":"Total number of items received in the request","examples":[2]},"succeeded":{"type":"integer","minimum":0.0,"title":"Succeeded","description":"Number of items successfully processed (status OK)","examples":[2]},"failed":{"type":"integer","minimum":0.0,"title":"Failed","description":"Number of items that failed validation or processing (status NOK)","examples":[0]},"results":{"items":{"$ref":"#/components/schemas/ListingAcknowledgementBulkResultItem"},"type":"array","title":"Results","description":"Per-item results preserving the original request order"}},"type":"object","required":["totalReceived","succeeded","failed","results"],"title":"ListingAcknowledgement.BulkResponse","description":"Bulk acknowledgement response schema."},"ListingAcknowledgementBulkResultItem":{"properties":{"listingIndex":{"type":"integer","minimum":0.0,"title":"Listingindex","description":"Zero-based index of this item in the original request list","examples":[0]},"listingId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Listingid","description":"As supplied in the request item, or `null` when it is missing or not a string","examples":["550e8400-e29b-41d4-a716-446655440000"]},"status":{"type":"string","enum":["OK","NOK"],"title":"Status","description":"Processing result - `OK` (new listing version created) or `NOK` (failed validation or processing)","examples":["OK"]},"listing":{"anyOf":[{"$ref":"#/components/schemas/ListingResponse"},{"type":"null"}],"description":"The listing as it now is (present for OK items, omitted for NOK items)"},"errors":{"anyOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"null"}],"description":"Structured error details (present for NOK items, omitted for OK items)","examples":[{"detail":[{"loc":["createdAt"],"msg":"Listing 'abc-123' version '2026-09-07T08:00:00Z' is no longer current","type":"conflict_error"}]}]}},"type":"object","required":["listingIndex","status"],"title":"ListingAcknowledgement.BulkResultItem","description":"Result for a single item in an acknowledgement bulk response."},"ListingAcknowledgementRequest":{"properties":{"listingId":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[A-Za-z0-9-]+$","title":"Listingid","description":"Functional ID of the flagged listing (scoped to the authenticated platform)","examples":["550e8400-e29b-41d4-a716-446655440000"]},"createdAt":{"type":"string","format":"date-time","title":"Createdat","description":"`createdAt` of the flagged listing version (UTC); refused with `conflict_error` when that version is no longer current","examples":["2026-09-07T08:00:00Z"]}},"type":"object","required":["listingId","createdAt"],"title":"ListingAcknowledgement.Request","description":"Acknowledgement of a flagged listing, submitted by the platform."}},"securitySchemes":{"OAuth2ClientCredentials":{"type":"oauth2","flows":{"clientCredentials":{"scopes":{},"tokenUrl":"https://pre-sdep.minvro.nl/api/auth/v1/token"}}}}},"servers":[{"url":"/api/str/v2"}]}