{"openapi":"3.1.0","info":{"title":"@mailwoman/api","version":"10.4.0","description":"The native Mailwoman HTTP API — engine-agnostic /v1 surface (parse, geocode, batch, resolve, format) with health, metrics, and an emitted OpenAPI document.","license":{"name":"AGPL-3.0-only OR LicenseRef-Commercial","identifier":"AGPL-3.0-only"},"contact":{"name":"Sister Software","url":"https://mailwoman.ai"}},"servers":[{"url":"http://{host}:{port}","variables":{"host":{"default":"127.0.0.1"},"port":{"default":"3000"}}}],"tags":[{"name":"parsing","description":"Split an address into its components."},{"name":"geocoding","description":"Resolve an address to coordinates."},{"name":"resolving","description":"Resolve an already-decoded address tree against the gazetteer."},{"name":"formatting","description":"Render address components to a string, the inverse of parsing."},{"name":"meta","description":"Service liveness, metrics and deploy-time operations."}],"security":[],"components":{"schemas":{"StampedParseResponse":{"allOf":[{"$ref":"#/components/schemas/ParseResponse"},{"type":"object","properties":{"engine":{"$ref":"#/components/schemas/EngineStamp"}}}],"description":"The parsed components and decoded tree."},"ParseResponse":{"type":"object","properties":{"input":{"type":"string"},"components":{"type":"array","items":{"$ref":"#/components/schemas/ParseComponent"}},"tree":{"$ref":"#/components/schemas/AddressTree"},"debug":{"type":["string","null"]}},"required":["input","components","tree","debug"],"description":"The parsed components and decoded tree."},"ParseComponent":{"type":"object","properties":{"tag":{"type":"string"},"value":{"type":"string"}},"required":["tag","value"],"description":"One parsed component in reading order."},"AddressTree":{"type":"object","properties":{"raw":{"type":"string"},"roots":{"type":"array","items":{"type":"object"}}},"required":["raw","roots"],"additionalProperties":true,"description":"A decoded address: the raw input and its top-level component nodes."},"EngineStamp":{"type":"object","properties":{"name":{"type":"string","enum":["mailwoman"]},"version":{"type":"string"},"license":{"type":"string"},"license_url":{"type":"string"},"notice":{"type":["string","null"]}},"required":["name","version","license","license_url","notice"],"additionalProperties":false},"APIError":{"type":"object","properties":{"error":{"type":"string"},"detail":{"type":["string","null"]}},"required":["error","detail"]},"InputModeSelection":{"type":"string","enum":["fragmented","formatted","auto"],"default":"auto","description":"The parse register, or `\"auto\"` to derive it from the input."},"ParseRequest":{"type":"object","properties":{"address":{"type":"string","maxLength":1024},"debug":{"type":"boolean","default":false},"input_mode":{"$ref":"#/components/schemas/InputModeSelection"}},"required":["address"]},"StampedGeocodeResult":{"allOf":[{"$ref":"#/components/schemas/GeocodeResult"},{"type":"object","properties":{"engine":{"$ref":"#/components/schemas/EngineStamp"}}}],"description":"One geocoded input: its coordinate, tier, components and evidence."},"GeocodeResult":{"type":"object","properties":{"input":{"type":"string"},"components":{"type":"object","properties":{"country":{"type":"string"},"region":{"type":"string"},"locality":{"type":"string"},"dependent_locality":{"type":"string"},"postcode":{"type":"string"},"subregion":{"type":"string"},"house_number":{"type":"string"},"street":{"type":"string"},"street_prefix":{"type":"string"},"street_prefix_particle":{"type":"string"},"street_suffix":{"type":"string"},"intersection_a":{"type":"string"},"intersection_b":{"type":"string"},"unit":{"type":"string"},"venue":{"type":"string"},"attention":{"type":"string"},"po_box":{"type":"string"},"cedex":{"type":"string"},"prefecture":{"type":"string"},"municipality":{"type":"string"},"district":{"type":"string"},"block":{"type":"string"},"sub_block":{"type":"string"},"building_number":{"type":"string"},"building_name":{"type":"string"},"locality_unit":{"type":"string"}}},"dropped_components":{"type":["array","null"],"items":{"type":"object","properties":{"tag":{"$ref":"#/components/schemas/ComponentTag"},"value":{"type":"string"},"kept":{"type":"string"}},"required":["tag","value","kept"]}},"unfollowed_components":{"type":["array","null"],"items":{"type":"object","properties":{"tag":{"$ref":"#/components/schemas/ComponentTag"},"value":{"type":"string"},"reason":{"type":"string","enum":["postcode_move_refused","rooftop_outside_locality"]},"distance_km":{"type":"number"}},"required":["tag","value","reason","distance_km"]}},"lat":{"type":["number","null"]},"lon":{"type":["number","null"]},"resolution_tier":{"$ref":"#/components/schemas/ResolutionTier"},"epistemic_status":{"$ref":"#/components/schemas/EpistemicStatus"},"derivation":{"$ref":"#/components/schemas/DerivationProjection"},"entity":{"type":["object","null"],"properties":{"name":{"type":"string"},"categoryID":{"type":["string","null"]},"confidence":{"type":"number"},"country":{"type":"string"}},"required":["name","categoryID","confidence","country"]},"rooftop":{"type":["object","null"],"properties":{"localityNorm":{"type":["string","null"]},"postcode":{"type":["string","null"]}},"required":["localityNorm","postcode"]},"uncertainty_m":{"type":["number","null"]},"locality":{"type":["string","null"]},"region":{"type":["string","null"]},"postcode":{"type":["string","null"]},"house_number":{"type":["string","null"]},"street":{"type":["string","null"]},"venue":{"type":["string","null"]},"dependent_locality":{"type":["string","null"]},"unit":{"type":["string","null"]},"countryCode":{"type":["string","null"]},"hierarchy":{"type":"array","items":{"$ref":"#/components/schemas/HierarchyEntry"}},"candidates":{"type":"array","items":{"$ref":"#/components/schemas/GeocodeCandidate"}},"postcode_country_scope":{"type":["string","null"]},"capital_promotion":{"type":["string","null"]},"variant_alias_exemption":{"$ref":"#/components/schemas/VariantAliasExemption"},"intent_markers":{"type":"array","items":{"$ref":"#/components/schemas/QueryIntentMarker"}},"admin_coherence":{"$ref":"#/components/schemas/AdminCoherenceReport"},"authoritative":{"$ref":"#/components/schemas/AuthoritativeAssertion"}},"required":["input","components","dropped_components","unfollowed_components","lat","lon","resolution_tier","epistemic_status","derivation","entity","rooftop","uncertainty_m","locality","region","postcode","house_number","street","venue","dependent_locality","unit","countryCode","hierarchy","candidates","postcode_country_scope","capital_promotion","variant_alias_exemption","intent_markers","admin_coherence","authoritative"],"description":"One geocoded input: its coordinate, tier, components and evidence."},"ComponentTag":{"type":"string","enum":["country","region","locality","dependent_locality","postcode","subregion","house_number","street","street_prefix","street_prefix_particle","street_suffix","intersection_a","intersection_b","unit","venue","attention","po_box","cedex","prefecture","municipality","district","block","sub_block","building_number","building_name","locality_unit"],"description":"A recognized address component tag."},"ResolutionTier":{"type":"string","enum":["address_point","interpolated","street","postcode","admin","venue","plus_code"],"description":"The geocoder tier that produced the coordinate."},"EpistemicStatus":{"type":"string","enum":["designated","observed","derived","inferred","unresolved"],"description":"What the evidence permits a consumer to claim about a value."},"DerivationProjection":{"type":["object","null"],"properties":{"status":{"$ref":"#/components/schemas/EpistemicStatus"},"constraints":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"evidence":{"$ref":"#/components/schemas/Evidence"},"contribution":{"type":"string"}},"required":["label","evidence","contribution"]}},"uncertaintyM":{"type":["number","null"]}},"required":["status","constraints","uncertaintyM"],"description":"The derivation behind an answer."},"Evidence":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["observation"]},"source":{"type":"string"},"vintage":{"type":["string","null"]},"value":{}},"required":["kind","source","vintage"]},{"type":"object","properties":{"kind":{"type":"string","enum":["exclusion"]},"source":{"type":"string"},"vintage":{"type":"string"},"scope":{"type":"object","properties":{"layer":{"type":"string"},"h3Cell":{"type":"number"},"basis":{"$ref":"#/components/schemas/CoverageBasis"},"fold":{"type":"string","description":"The fold both the layer's builder and the probe used."}},"required":["layer","h3Cell","basis","fold"]}},"required":["kind","source","vintage","scope"]},{"type":"object","properties":{"kind":{"type":"string","enum":["relation"]},"source":{"type":"string"},"vintage":{"type":"string"},"relationship":{"type":"string"},"assertion":{"type":"string","enum":["authoritative","inferred"]},"score":{"type":["number","null"]}},"required":["kind","source","vintage","relationship","assertion","score"]},{"type":"object","properties":{"kind":{"type":"string","enum":["prior"]},"source":{"type":"string"},"label":{"type":"string"},"weight":{"type":"number"}},"required":["kind","source","label","weight"]}],"description":"One piece of typed evidence, discriminated by `kind`."},"CoverageBasis":{"type":"string","enum":["designated","surveyed","source_present"]},"HierarchyEntry":{"type":"object","properties":{"tag":{"type":"string"},"value":{"type":"string"},"name":{"type":"string"},"lat":{"type":["number","null"]},"lon":{"type":["number","null"]},"placeID":{"type":["string","null"]},"in_winner_lineage":{"type":["boolean","null"]}},"required":["tag","value","name","lat","lon","placeID","in_winner_lineage"],"description":"One resolved admin level, most specific first."},"GeocodeCandidate":{"type":"object","properties":{"name":{"type":"string"},"tag":{"type":"string"},"lat":{"type":"number"},"lon":{"type":"number"},"countryCode":{"type":["string","null"]},"placeID":{"type":["string","null"]}},"required":["name","tag","lat","lon","countryCode","placeID"],"description":"A ranked candidate place."},"VariantAliasExemption":{"type":"string","enum":["applied","not_applied"],"description":"Whether the variant-alias exemption chose a node's winner."},"QueryIntentMarker":{"type":"object","properties":{"kind":{"$ref":"#/components/schemas/QueryKind"},"code":{"$ref":"#/components/schemas/QueryIntentCode"},"mechanism":{"type":"string"},"message":{"type":"string"},"evidence":{"type":["object","null"],"additionalProperties":{}}},"required":["kind","code","mechanism","message","evidence"],"description":"A query-intent advisory; it never changes the answer."},"QueryKind":{"type":"string","enum":["postcode_only","locality_only","structured_address","intersection","po_box","landmark","poi_query","vague","bare_toponym","route_pair","near_me","poi_category"],"description":"The query kind the kind classifier assigned."},"QueryIntentCode":{"type":"string","enum":["declared_ambiguity","declared_fork","focus_point_required","poi_category","coverage_qualified_absence","authority_designation","declared_coarser_answer"]},"AdminCoherenceReport":{"type":["object","null"],"properties":{"region":{"type":"string","enum":["confirmed","contradicted","unstated","unverifiable"]},"country":{"type":"string","enum":["confirmed","contradicted","unstated","unverifiable"]}},"required":["region","country"],"description":"Flag-only verdicts for the parsed region and country."},"AuthoritativeAssertion":{"type":["object","null"],"properties":{"provider":{"type":"string"},"status":{"type":"string","enum":["matched","ambiguous","refused","transport_error"]},"matches":{"type":["array","null"],"items":{"type":"object","properties":{"provider_place_id":{"type":"string"},"object_ids":{"type":["object","null"],"additionalProperties":{"type":"string"}},"canonical_fields":{"type":["object","null"],"additionalProperties":{"type":"string"}},"lat":{"type":["number","null"]},"lon":{"type":["number","null"]},"precision":{"type":["string","null"]},"match_status":{"type":"string","enum":["exact","approximate"]},"provider_score":{"type":["number","null"]}},"required":["provider_place_id","object_ids","canonical_fields","lat","lon","precision","match_status","provider_score"]}},"attribution":{"type":["string","null"]},"license":{"type":["string","null"]},"retrieved_at":{"type":["string","null"]},"dataset_version":{"type":["string","null"]},"error":{"type":["string","null"]}},"required":["provider","status","matches","attribution","license","retrieved_at","dataset_version","error"],"description":"A configured authoritative provider's answer."},"GeocodeRequest":{"type":"object","properties":{"address":{"type":"string","maxLength":1024},"input_mode":{"$ref":"#/components/schemas/InputModeSelection"}},"required":["address"]},"StampedBatchResponse":{"allOf":[{"$ref":"#/components/schemas/BatchResponse"},{"type":"object","properties":{"engine":{"$ref":"#/components/schemas/EngineStamp"}}}],"description":"One result per input address, in input order."},"BatchResponse":{"type":"object","properties":{"results":{"type":"array","items":{"anyOf":[{"$ref":"#/components/schemas/GeocodeResult"},{"$ref":"#/components/schemas/BatchRowError"}]}}},"required":["results"],"description":"One result per input address, in input order."},"BatchRowError":{"type":"object","properties":{"input":{"type":"string"},"error":{"type":"string"}},"required":["input","error"],"description":"A row that failed, isolated from its neighbors."},"BatchRequest":{"type":"object","properties":{"addresses":{"type":"array","items":{"type":"string","maxLength":1024}},"input_mode":{"$ref":"#/components/schemas/InputModeSelection"}},"required":["addresses"]},"StampedResolveResponse":{"allOf":[{"$ref":"#/components/schemas/ResolveResponse"},{"type":"object","properties":{"engine":{"$ref":"#/components/schemas/EngineStamp"}}}],"description":"The tree, decorated with gazetteer coordinates and attribution."},"ResolveResponse":{"type":"object","properties":{"tree":{"$ref":"#/components/schemas/AddressTree"}},"required":["tree"],"description":"The tree, decorated with gazetteer coordinates and attribution."},"ResolveRequest":{"type":"object","properties":{"tree":{"$ref":"#/components/schemas/AddressTree"},"opts":{"type":"object","properties":{},"default":{},"additionalProperties":{},"description":"Resolver options."}},"required":["tree"]},"ReloadResponse":{"type":"object","properties":{"reloaded":{"type":"boolean"},"versions":{}},"required":["reloaded"],"description":"The versioned data switchover result."},"StampedFormatResponse":{"allOf":[{"$ref":"#/components/schemas/FormatResponse"},{"type":"object","properties":{"engine":{"$ref":"#/components/schemas/EngineStamp"}}}],"description":"The rendered address and its canonical match key."},"FormatResponse":{"type":"object","properties":{"formatted":{"type":"string"},"canonicalKey":{"type":"string"}},"required":["formatted","canonicalKey"],"description":"The rendered address and its canonical match key."},"FormatRequest":{"type":"object","properties":{"components":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]}},"country":{"type":"string"},"options":{"type":"object","properties":{},"default":{},"additionalProperties":{},"description":"Formatter options."}},"required":["components","country"]},"HealthResponse":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]},"uptime_s":{"type":"number"}},"required":["status","uptime_s"],"additionalProperties":{},"description":"Liveness and the engine's health block."},"MetricsSnapshot":{"type":"object","properties":{"uptime_s":{"type":"number"},"timings":{"type":"object","properties":{"total":{"type":"number"},"errors":{"type":"number"},"tiers":{"type":"object","additionalProperties":{"type":"number"}},"latency_ms":{"type":["object","null"],"properties":{"p50":{"type":"number"},"p90":{"type":"number"},"p99":{"type":"number"},"max":{"type":"number"}},"required":["p50","p90","p99","max"]},"latency_samples":{"type":"number"}},"required":["total","errors","tiers","latency_ms","latency_samples"]}},"required":["uptime_s","timings"],"description":"The live in-process timing metrics snapshot."}},"parameters":{}},"paths":{"/v1/parse":{"get":{"operationId":"parseAddressQuery","summary":"Parse an address (query string)","tags":["parsing"],"parameters":[{"schema":{"type":"string","description":"The address to parse."},"required":false,"description":"The address to parse.","name":"address","in":"query"},{"schema":{"type":"string","enum":["true","false"],"default":"false","description":"`\"true\"` to include a diagnostic report."},"required":false,"description":"`\"true\"` to include a diagnostic report.","name":"debug","in":"query"},{"schema":{"$ref":"#/components/schemas/InputModeSelection"},"required":false,"description":"The parse register, or `\"auto\"` to derive it from the input.","name":"input_mode","in":"query"}],"responses":{"200":{"description":"The parsed components and decoded tree.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StampedParseResponse"}}}},"400":{"description":"`address` is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/APIError"}}}},"501":{"description":"The backing engine method is not wired for this deployment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/APIError"}}}}}},"post":{"operationId":"parseAddress","summary":"Parse an address (JSON body)","tags":["parsing"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParseRequest"}}}},"responses":{"200":{"description":"The parsed components and decoded tree.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StampedParseResponse"}}}},"400":{"description":"`address` is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/APIError"}}}},"501":{"description":"The backing engine method is not wired for this deployment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/APIError"}}}}}}},"/v1/geocode":{"post":{"operationId":"geocodeAddress","summary":"Geocode an address to coordinates","tags":["geocoding"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeocodeRequest"}}}},"responses":{"200":{"description":"One geocoded input: its coordinate, tier, components and evidence.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StampedGeocodeResult"}}}},"400":{"description":"`address` is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/APIError"}}}},"503":{"description":"The geocoding engine is not wired for this deployment (dependencies missing).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/APIError"}}}}}}},"/v1/batch":{"post":{"operationId":"geocodeBatch","summary":"Geocode a batch of addresses","tags":["geocoding"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchRequest"}}}},"responses":{"200":{"description":"One result per input address, in input order.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StampedBatchResponse"}}}},"400":{"description":"The body must be `{ addresses: string[] }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/APIError"}}}},"413":{"description":"`addresses.length` exceeds the configured batch cap.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/APIError"}}}},"503":{"description":"The geocoding engine is not wired for this deployment (dependencies missing).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/APIError"}}}}}}},"/v1/resolve":{"post":{"operationId":"resolveTree","summary":"Resolve an already-decoded address tree against the gazetteer","tags":["resolving"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveRequest"}}}},"responses":{"200":{"description":"The tree, decorated with gazetteer coordinates and attribution.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StampedResolveResponse"}}}},"400":{"description":"The body must be `{ tree: AddressTree, opts? }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/APIError"}}}},"503":{"description":"The resolver is not wired for this deployment (dependencies missing).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/APIError"}}}}}}},"/v1/reload":{"post":{"operationId":"reloadData","summary":"Reload versioned data extracts (deploy-only; check at ingress)","tags":["meta"],"responses":{"200":{"description":"The versioned data switchover result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReloadResponse"}}}},"503":{"description":"The geocoding engine is not wired for this deployment (dependencies missing).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/APIError"}}}}}}},"/v1/format":{"post":{"operationId":"formatAddress","summary":"Render address components to a string and canonical match key","tags":["formatting"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormatRequest"}}}},"responses":{"200":{"description":"The rendered address and its canonical match key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StampedFormatResponse"}}}},"400":{"description":"Invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/APIError"}}}}}}},"/health":{"get":{"operationId":"retrieveHealth","summary":"Liveness + engine health","tags":["meta"],"responses":{"200":{"description":"Liveness and the engine's health block.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/metrics":{"get":{"operationId":"retrieveMetrics","summary":"In-process timing metrics snapshot","tags":["meta"],"responses":{"200":{"description":"The live in-process timing metrics snapshot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricsSnapshot"}}}}}}}},"webhooks":{}}
