{"openapi":"3.1.0","info":{"title":"RightDoor API","version":"1","description":"Dutch and Belgian address lookup and validation against the official open registers (Kadaster BAG; BeST Address, FPS BOSA, CC BY 4.0). Callers must fail open: on a timeout, 5xx or anything uncertain, accept the address and validate it again later."},"servers":[{"url":"https://api.rightdoor.eu"}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"An API key (rd_live_… / rd_test_…), a publishable key of the embedded address form (rd_pk_live_… / rd_pk_test_…: lookup, suggest and validate, from its allowed origins, with a sessionId), or a Shopify session token on the checkout routes. Only in the Authorization header, never in the URL."}},"schemas":{"HealthResponse":{"type":"object","properties":{"status":{"type":"string","enum":["ok","degraded"]},"database":{"type":"string","enum":["up","down"]},"datasets":{"type":"array","items":{"$ref":"#/components/schemas/DatasetStatus"}},"checkedAt":{"type":"string"}},"required":["status","database","datasets","checkedAt"]},"DatasetStatus":{"type":"object","properties":{"country":{"type":"string","minLength":2,"maxLength":2},"version":{"type":"string"},"activatedAt":{"type":"string"},"ageHours":{"type":"number"}},"required":["country","version","activatedAt","ageHours"]},"LookupResponse":{"type":"object","properties":{"addresses":{"type":"array","items":{"$ref":"#/components/schemas/LookupAddress"}},"additions":{"type":"array","items":{"type":["string","null"]}},"issues":{"type":"array","items":{"$ref":"#/components/schemas/Issue"}},"nextStep":{"type":"string"},"meta":{"$ref":"#/components/schemas/ResponseMeta"}},"required":["addresses","additions","issues","nextStep","meta"]},"LookupAddress":{"type":"object","properties":{"street":{"type":"string"},"houseNumber":{"type":["integer","null"]},"houseNumberSuffix":{"type":["string","null"]},"unit":{"type":["string","null"]},"unitType":{"$ref":"#/components/schemas/UnitType"},"addition":{"type":["string","null"]},"postcode":{"type":"string"},"locality":{"type":"string"},"planned":{"type":"boolean"},"formatted":{"type":"array","items":{"type":"string"}},"carrier":{"$ref":"#/components/schemas/CarrierAddress"}},"required":["street","houseNumber","houseNumberSuffix","unit","unitType","addition","postcode","locality","planned","formatted","carrier"]},"UnitType":{"type":["string","null"],"enum":["toevoeging","bus",null]},"CarrierAddress":{"type":"object","properties":{"street":{"type":"string"},"houseNumber":{"type":"string"},"houseNumberAddition":{"type":["string","null"]},"postcode":{"type":"string"},"city":{"type":"string"},"countryCode":{"$ref":"#/components/schemas/CountryCode"},"warnings":{"type":"array","items":{"$ref":"#/components/schemas/Issue"}}},"required":["street","houseNumber","houseNumberAddition","postcode","city","countryCode","warnings"]},"CountryCode":{"type":"string","enum":["NL","BE"],"description":"ISO 3166-1 alpha-2"},"Issue":{"type":"object","properties":{"code":{"$ref":"#/components/schemas/IssueCode"},"severity":{"$ref":"#/components/schemas/IssueSeverity"},"field":{"$ref":"#/components/schemas/AddressField"},"unitType":{"$ref":"#/components/schemas/UnitType"},"message":{"type":"string"}},"required":["code","severity","message"]},"IssueCode":{"type":"string","enum":["FORMAT_INVALID","MISSING_HOUSE_NUMBER","POSTCODE_NOT_FOUND","HOUSE_NUMBER_NOT_FOUND","SUFFIX_NOT_FOUND","UNIT_REQUIRED","UNIT_NOT_FOUND","STREET_MISMATCH","CITY_MISMATCH","ADDRESS_PLANNED","CARRIER_LINE_TOO_LONG","PO_BOX_NOT_ALLOWED","UNSUPPORTED_COUNTRY","COUNTRY_AMBIGUOUS","UNVERIFIED_CONFIRMED_BY_CUSTOMER"]},"IssueSeverity":{"type":"string","enum":["error","warning","info"]},"AddressField":{"type":"string","enum":["address1","address2","zip","city","countryCode","address"]},"ResponseMeta":{"type":"object","properties":{"datasetVersion":{"type":["string","null"]},"source":{"type":["string","null"],"description":"Register the answer comes from, e.g. \"Kadaster BAG\""},"attribution":{"type":["string","null"]},"language":{"$ref":"#/components/schemas/Language"}},"required":["datasetVersion","source","attribution","language"]},"Language":{"type":"string","enum":["nl","fr","de","en"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","PAYLOAD_TOO_LARGE","VALIDATION_FAILED","RATE_LIMITED","QUOTA_EXCEEDED","DAILY_CAP_REACHED","INTERNAL_ERROR","SERVICE_UNAVAILABLE"]},"message":{"type":"string"},"nextStep":{"type":"string"},"upgradeUrl":{"type":"string"}},"required":["code","message"]}},"required":["error"]},"Carrier":{"type":"string","enum":["postnl","bpost","dhl","sendcloud"]},"SessionId":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[\\w.:-]+$","description":"Client-generated id for one address being entered: suggest and lookup calls plus the validate that follows count as one verification. Required with a publishable key."},"SuggestResponse":{"type":"object","properties":{"suggestions":{"type":"array","items":{"$ref":"#/components/schemas/StreetSuggestion"},"maxItems":10},"issues":{"type":"array","items":{"$ref":"#/components/schemas/Issue"}},"meta":{"$ref":"#/components/schemas/ResponseMeta"}},"required":["suggestions","issues","meta"]},"StreetSuggestion":{"type":"object","properties":{"street":{"type":"string"},"locality":{"type":"string"},"postcode":{"type":["string","null"]}},"required":["street","locality","postcode"]},"ValidateResponse":{"type":"object","properties":{"status":{"$ref":"#/components/schemas/Verdict"},"normalized":{"$ref":"#/components/schemas/NormalizedAddress"},"formatted":{"type":["array","null"],"items":{"type":"string"}},"match":{"$ref":"#/components/schemas/AddressMatch"},"suggestions":{"type":"array","items":{"$ref":"#/components/schemas/NormalizedAddress"},"maxItems":10},"confidence":{"$ref":"#/components/schemas/Confidence"},"blocking":{"type":"boolean"},"issues":{"type":"array","items":{"$ref":"#/components/schemas/Issue"}},"carrier":{"allOf":[{"$ref":"#/components/schemas/CarrierAddress"},{"type":["object","null"]}]},"nextStep":{"type":"string"},"meta":{"$ref":"#/components/schemas/ResponseMeta"},"receipt":{"type":"string"}},"required":["status","normalized","formatted","match","suggestions","confidence","blocking","issues","carrier","nextStep","meta"]},"Verdict":{"type":"string","enum":["valid","corrected","ambiguous","invalid"]},"NormalizedAddress":{"type":["object","null"],"properties":{"address1":{"type":"string"},"address2":{"type":["string","null"]},"zip":{"type":"string"},"city":{"type":"string"},"countryCode":{"$ref":"#/components/schemas/CountryCode"}},"required":["address1","address2","zip","city","countryCode"]},"AddressMatch":{"type":["object","null"],"properties":{"street":{"type":"string"},"houseNumber":{"type":["integer","null"]},"houseNumberSuffix":{"type":["string","null"]},"unit":{"type":["string","null"]},"unitType":{"$ref":"#/components/schemas/UnitType"},"locality":{"type":"string"},"postcode":{"type":"string"}},"required":["street","houseNumber","houseNumberSuffix","unit","unitType","locality","postcode"]},"Confidence":{"type":"string","enum":["high","medium","low"]},"ValidateRequest":{"type":"object","properties":{"countryCode":{"type":"string","minLength":2,"maxLength":2},"address1":{"type":"string","maxLength":200,"description":"Street and house number, as the customer typed it"},"address2":{"type":["string","null"],"maxLength":200,"description":"Apartment, unit, addition (NL toevoeging / BE bus)"},"zip":{"type":"string","maxLength":200,"description":"Postcode"},"city":{"type":["string","null"],"maxLength":200,"description":"City"},"customerConfirmed":{"type":"boolean","default":false,"description":"Set after the customer explicitly confirmed the address; blocking is then limited to hard format errors and disallowed PO boxes"},"allowPoBox":{"type":"boolean","default":false},"lang":{"$ref":"#/components/schemas/Language"},"carrier":{"$ref":"#/components/schemas/Carrier"},"sessionId":{"$ref":"#/components/schemas/SessionId"}},"required":["countryCode","address1","zip"]}},"parameters":{}},"paths":{"/health":{"get":{"summary":"Liveness, database reachability and dataset version per country","responses":{"200":{"description":"Healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}},"503":{"description":"Degraded: the database is unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/v1/nl/lookup":{"get":{"summary":"NL: postcode + huisnummer → every address, with the toevoegingen to choose from","security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","maxLength":200,"description":"Postcode"},"required":false,"description":"Postcode","name":"postcode","in":"query"},{"schema":{"type":"string","pattern":"^\\d{1,6}$","description":"House number, digits only","example":"12"},"required":false,"description":"House number, digits only","name":"number","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"Street name (required for BE)"},"required":false,"description":"Street name (required for BE)","name":"street","in":"query"},{"schema":{"$ref":"#/components/schemas/Language"},"required":false,"name":"lang","in":"query"},{"schema":{"$ref":"#/components/schemas/Carrier"},"required":false,"name":"carrier","in":"query"},{"schema":{"$ref":"#/components/schemas/SessionId"},"required":false,"description":"Client-generated id for one address being entered: suggest and lookup calls plus the validate that follows count as one verification. Required with a publishable key.","name":"sessionId","in":"query"}],"responses":{"200":{"description":"Addresses at the number (empty with an issue when there are none)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LookupResponse"}}}},"401":{"description":"Missing or invalid credential","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The credential lacks the address:verify scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"A required parameter is missing or malformed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit (RATE_LIMITED, with Retry-After) or monthly quota (QUOTA_EXCEEDED, with upgradeUrl)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Register temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/be/lookup":{"get":{"summary":"BE: postcode + street + number → matching addresses with box numbers","security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","maxLength":200,"description":"Postcode"},"required":false,"description":"Postcode","name":"postcode","in":"query"},{"schema":{"type":"string","pattern":"^\\d{1,6}$","description":"House number, digits only","example":"12"},"required":false,"description":"House number, digits only","name":"number","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"Street name (required for BE)"},"required":false,"description":"Street name (required for BE)","name":"street","in":"query"},{"schema":{"$ref":"#/components/schemas/Language"},"required":false,"name":"lang","in":"query"},{"schema":{"$ref":"#/components/schemas/Carrier"},"required":false,"name":"carrier","in":"query"},{"schema":{"$ref":"#/components/schemas/SessionId"},"required":false,"description":"Client-generated id for one address being entered: suggest and lookup calls plus the validate that follows count as one verification. Required with a publishable key.","name":"sessionId","in":"query"}],"responses":{"200":{"description":"Addresses at the number (empty with an issue when there are none)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LookupResponse"}}}},"401":{"description":"Missing or invalid credential","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The credential lacks the address:verify scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"A required parameter is missing or malformed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit (RATE_LIMITED, with Retry-After) or monthly quota (QUOTA_EXCEEDED, with upgradeUrl)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Register temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/{country}/lookup":{"get":{"summary":"Every valid address at a postcode + number","description":"Required parameters depend on the country: NL postcode + number; BE postcode + street + number. Unsupported countries answer UNSUPPORTED_COUNTRY.","security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","minLength":2,"maxLength":2,"example":"nl"},"required":true,"name":"country","in":"path"},{"schema":{"type":"string","maxLength":200,"description":"Postcode"},"required":false,"description":"Postcode","name":"postcode","in":"query"},{"schema":{"type":"string","pattern":"^\\d{1,6}$","description":"House number, digits only","example":"12"},"required":false,"description":"House number, digits only","name":"number","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"Street name (required for BE)"},"required":false,"description":"Street name (required for BE)","name":"street","in":"query"},{"schema":{"$ref":"#/components/schemas/Language"},"required":false,"name":"lang","in":"query"},{"schema":{"$ref":"#/components/schemas/Carrier"},"required":false,"name":"carrier","in":"query"},{"schema":{"$ref":"#/components/schemas/SessionId"},"required":false,"description":"Client-generated id for one address being entered: suggest and lookup calls plus the validate that follows count as one verification. Required with a publishable key.","name":"sessionId","in":"query"}],"responses":{"200":{"description":"Addresses at the number (empty with an issue when there are none)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LookupResponse"}}}},"401":{"description":"Missing or invalid credential","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The credential lacks the address:verify scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"A required parameter is missing or malformed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit (RATE_LIMITED, with Retry-After) or monthly quota (QUOTA_EXCEEDED, with upgradeUrl)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Register temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/suggest":{"get":{"summary":"Street suggestions while the customer types","description":"Up to 10 streets matching what was typed, in any of the register's languages (Brussels: Dutch and French). With `postcode`, only that postcode's streets; without it, country-wide from 3 letters. Send the same `sessionId` with the validate call that follows: the suggestions and that validation count as one verification.","security":[{"bearer":[]}],"parameters":[{"schema":{"type":"string","minLength":2,"maxLength":2,"description":"ISO country code","example":"nl"},"required":true,"description":"ISO country code","name":"country","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":100,"description":"What the customer has typed so far (street name, possibly partial)","example":"Wetstr"},"required":true,"description":"What the customer has typed so far (street name, possibly partial)","name":"q","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"Postcode, when the customer has already entered it: suggestions are then limited to its streets"},"required":false,"description":"Postcode, when the customer has already entered it: suggestions are then limited to its streets","name":"postcode","in":"query"},{"schema":{"$ref":"#/components/schemas/Language"},"required":false,"name":"lang","in":"query"},{"schema":{"$ref":"#/components/schemas/SessionId"},"required":false,"description":"Client-generated id for one address being entered: suggest and lookup calls plus the validate that follows count as one verification. Required with a publishable key.","name":"sessionId","in":"query"}],"responses":{"200":{"description":"Suggestions (empty with an issue when the postcode is invalid or unknown)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuggestResponse"}}}},"401":{"description":"Missing or invalid credential","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The credential lacks the address:verify scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"A parameter is missing or malformed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit (RATE_LIMITED, with Retry-After) or monthly quota (QUOTA_EXCEEDED, with upgradeUrl)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Register temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/validate":{"post":{"summary":"Validate a Shopify-shaped address against the official register","description":"Returns a verdict (valid | corrected | ambiguous | invalid), the normalised address, suggestions, issues with localised messages, carrier-ready fields and a next step. `blocking` is conservative advice: callers must fail open (accept the address) on timeouts, 5xx and anything uncertain.","security":[{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateRequest"}}}},"responses":{"200":{"description":"Verdict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateResponse"}}}},"401":{"description":"Missing or invalid credential","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The credential lacks the address:verify scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Body larger than 64 KB","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Invalid request (e.g. a field longer than 200 characters)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit (RATE_LIMITED, with Retry-After) or monthly quota (QUOTA_EXCEEDED, with upgradeUrl)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Register temporarily unavailable: accept the address and re-validate later","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"webhooks":{}}