iOS SDK reference
Every public symbol of the Dock Swift package as the Swift compiler declares it, with its doc comment: from the symbol graph Xcode and DocC read, one block per source file, Client.swift first. Written from sdk/swift/Sources/Dock by scripts/ios-reference.ts; make test-docs fails when this page is older than the code, or when a type, function, or class or protocol member has no doc comment. How to use each call, with examples: iOS SDK.
Client.swift
swift
/// Version of this SDK. Semantic versioning (PLAN.md 21).
let dockSDKVersion: String
/// The dock API, used when Client(key:) gets no baseURL.
let defaultBaseURL: URL
/// Ends per side in one matrix call, as the API's MATRIX_MAX (api/src/modules/route/route-input.ts).
let matrixMax: Int
/// Contours in one isochrone call, as the API's CONTOURS_MAX (api/src/modules/route/route-input.ts).
let isochroneContoursMax: Int
/// The longest contour in minutes, as the API's CONTOUR_MINUTES_MAX.
let isochroneMinutesMax: Int
/// Points in one matching call, as the API's TRACE_MAX (api/src/modules/route/route-input.ts); at least 2.
let matchingMax: Int
/// Ends a route passes between from and to, as the API's VIA_MAX (api/src/modules/route/route-input.ts).
let routeViaMax: Int
/// Stops in one optimizedTrips call, as the API's STOPS_MAX (api/src/modules/route/route-input.ts); at least 2.
let optimizedTripsMax: Int
/// The widest tilequery radius in metres, as the API's TILEQUERY_RADIUS_MAX_M (api/src/modules/tiles/tilequery.ts).
let tilequeryRadiusMaxM: Double
/// Features in one tilequery answer, as the API's TILEQUERY_LIMIT_MAX; 5 when no limit is sent.
let tilequeryLimitMax: Int
/// Same shape as the API's key check (api/src/modules/auth/api-key.ts): dk_ and 32 of 0-9, a-z without i, l, o, u.
func isValidKey(_ key: String) -> Bool
/// Sends one request. URLSession by default; tests and apps with their own networking pass another.
protocol DockTransport : Sendable {
/// The response's bytes and HTTP response. Throws when no response came back.
func send(_ request: URLRequest) async throws -> (Data, HTTPURLResponse)
}
/// The default DockTransport: one URLSession data task per request.
struct URLSessionTransport: DockTransport, Sendable {
let session: URLSession
init(session: URLSession = .shared)
func send(_ request: URLRequest) async throws -> (Data, HTTPURLResponse)
}
/// An API refusal or a failed request. `code` is the API's `error` field (invalid_code, not_found, rate_limited,
/// quota_exceeded, miss_cap, ...), or `network` when no response came back.
struct DockError: Equatable, Error, LocalizedError, Sendable {
/// HTTP status, 0 when no response came back.
let status: Int
let code: String
let message: String
/// Seconds, from Retry-After on 429 and 503. nil otherwise.
let retryAfter: Double?
var errorDescription: String? { get }
}
/// A route the API marks deprecated (Deprecation, Sunset and Link headers, PLAN.md 17).
struct DeprecationNotice: Equatable, Sendable {
/// "GET /v1/door/:code", the route, not the URL: no codes, no query.
let route: String
/// Day it was announced, YYYY-MM-DD Ulaanbaatar, or nil if the header did not parse.
let deprecated: String?
/// Day the route stops answering (410 sunset from 00:00 Ulaanbaatar), YYYY-MM-DD, or nil.
let sunset: String?
/// The status page with the replacement route, or nil.
let link: String?
}
/// Notice from response headers, nil when the route is not deprecated.
func deprecationNotice(route: String, headers: [String : String]) -> DeprecationNotice?
/// The dock API v1. Calls send the key in the Authorization header. Map requests to this API (TileJSON, tiles)
/// get ?access_token= through authorizedURL(_:), for MapLibre Native. The key never shows in print, dump or logs.
final class Client: CustomDebugStringConvertible, CustomReflectable, CustomStringConvertible, Sendable {
/// Where calls go: https://geo.dock.mn unless another was given.
let baseURL: URL
/// - key: dk_ and 32 characters. Lives here only.
/// - baseURL: default https://geo.dock.mn.
/// - onDeprecation: called once per route when an answer says the route is deprecated. Default: one line to the
/// console per route. Pass `{ _ in }` to stay quiet.
/// - telemetry: share geocode searches and picks with dock (PLAN.md 18). Default false. Set true only after the
/// user opted in; setTelemetry(_:) changes it later. Sent: the typed text, the result count, the pick. Not
/// sent: time, point, device, session.
/// - placeCache: places the user picked, kept on this device so geocode still answers when the network is down
/// (PLAN.md 18). Default on, in memory, 100 places. Pass PlaceCacheOptions(store: UserDefaultsPlaceStore()) to
/// keep them across launches, nil for none.
init(key: String, baseURL: URL = defaultBaseURL, transport: DockTransport = URLSessionTransport(), onDeprecation: (@Sendable (DeprecationNotice) -> Void)? = nil, telemetry: Bool = false, placeCache: PlaceCacheOptions? = PlaceCacheOptions()) throws
/// Client(baseURL: ...). Never the key.
var description: String { get }
/// The same as description. Never the key.
var debugDescription: String { get }
/// baseURL only, so dump(_:) and the debugger never show the key.
var customMirror: Mirror { get }
/// Name or address to places, best first. Needs geocode:read. limit 1 to 20. With no network (DockError code
/// network) the answer comes from places the user picked on this device, with `offline` true, score = times
/// picked, fields as last seen; with none of them matching, the network error is thrown. `proximity` is where
/// the person is or the map centre: among names the query starts equally well, nearer places come first. It is
/// sent with this request only, never kept or sent with telemetry; offline answers do not read it. `types` (API
/// 0.70.0, Mapbox's types): only these kinds, chosen before the limit, offline too; sent once each, in the order
/// given. nil or empty: every kind.
func geocode(_ q: String, limit: Int? = nil, proximity: LonLat? = nil, types: [GeocodeType]? = nil) async throws -> GeocodeResponse
/// The user's consent changed. Off drops every search not yet sent. On, searches go in batches of 50 and when
/// the app goes to the background.
func setTelemetry(_ on: Bool)
/// The user chose this result from a geocode list. It is kept on this device for offline search (placeCache),
/// and goes to telemetry only while telemetry is on.
func pick(_ result: GeocodeResult)
/// Places the user picked on this device, most picked first: a "your places" list. [] with placeCache nil.
func places() -> [Place]
/// The user asked to forget their places: clears memory and the store.
func forgetPlaces()
/// Sends what is waiting now, for example when an order is placed. nil when telemetry is off or nothing waits.
/// A failed send throws and its searches are not kept: no retry, nothing stored on the device.
@discardableResult func flushTelemetry() async throws -> SearchTelemetryReceipt?
/// Starts recording the user's trip (PLAN.md 15). Off until called; call it only after the user said yes.
/// Points stay in memory, never on disk. `source` gives the fixes (the app's CLLocationManager, see
/// PositionFix(_:)). Throws trace_running when a trip is being recorded or still waits to be sent.
func startTrace(consent: Consent, source: PositionSource, maxAccuracyM: Double = traceMaxAccuracyM) throws
/// true while a trip is being recorded.
var tracing: Bool { get }
/// Stops recording and sends the trip to POST /v1/traces, split every 20,000 points. Needs trace:write. Keep
/// each receipt's id: deleteTrace(_:) erases the trip. [] when nothing was recorded or under 2 points. A failed
/// send throws and keeps the unsent points in memory: call stopTrace() again to retry, cancelTrace() to drop them.
@discardableResult func stopTrace() async throws -> [TraceReceipt]
/// Stops recording and drops the trip unsent: the user changed their mind.
func cancelTrace()
/// One of your organization's trips as stored, GeoJSON [lon, lat, t]: the export. Needs trace:write.
func trace(_ id: String) async throws -> Trace
/// Erases a trip's points and times now. The id is kept, never reused. Twice is fine. Needs trace:write.
@discardableResult func deleteTrace(_ id: String) async throws -> TraceDeleted
/// Trips per 500 m cell in a month, all partners together (PLAN.md 18, 19). `month` is YYYY-MM (Ulaanbaatar),
/// published 14 days after it ends (400 month_open before). `bbox` inside Mongolia, sides at most 1 degree. A cell
/// shows only with trips from 3 or more organizations; no cell means too few, not zero. Needs insights:read.
func traceCells(month: String, bbox: BBox) async throws -> TraceCells
/// Moving speed per 500 m cell in a month, all partners together: where traffic is slow (PLAN.md 18, 19). The same
/// grid, month and bbox as traceCells. kmH is the counted meters over the counted seconds, to 0.1; parking and the
/// last 200 m are left out. Per cell, not per road. A cell shows only under the trip cells rule; no cell means too
/// few trips, not a slow road. No trip count. Needs insights:read.
func traceSpeeds(month: String, bbox: BBox) async throws -> TraceSpeeds
/// Moving speed per road in a month, all partners together: speed profiles per road (PLAN.md 18, 19). Each trip is
/// matched to OSM ways with Valhalla when it is stored; a segment counts on a way under the traceSpeeds rule when
/// both its points matched that way. kmH is the counted meters over the counted seconds, to 0.1. A road shows only
/// under the trip cells rule; no road means too few trips, not a slow road. The line is dock's current road with
/// that OSM id. No trip count. band gives one hour band's trips only, under the same rule on its own trips; nil, all
/// hours. rule["hours"] says which. band needs API 0.49.0.
/// Needs insights:read.
func traceRoads(month: String, bbox: BBox, band: RoadBand? = nil) async throws -> TraceRoads
/// Your organization's own trips per cell, the same grid: your dashboard (PLAN.md 18, 20.13). Every cell with one of
/// your trips, no other organization read. The month you are in is answered too; `closed` is true once the counts
/// are final. Needs trace:read, a read-only scope: trace:write does not read it.
func ownTraceCells(month: String, bbox: BBox) async throws -> OwnTraceCells
/// Your organization's arrival minutes in a month: how long your trips spend in the last 200 m, parking and the
/// walk to the door included (PLAN.md 18). `month` is YYYY-MM (Ulaanbaatar). Month totals with median, p75 and p90,
/// trips per minute, and up to 100 end cells on the trip cells grid, slowest first. No other organization is read.
/// `closed` is true from 14 days after the month ends. Needs trace:read.
func ownArrivals(month: String) async throws -> OwnArrivals
/// When your organization's trips start in a month: each trip once, at the Ulaanbaatar weekday and hour of its first
/// stored point (PLAN.md 18). `month` is YYYY-MM (Ulaanbaatar). Month total, 7 weekday counts, 24 hour counts, and
/// every weekday and hour with trips. No other organization is read. `closed` is true from 14 days after the month
/// ends. Needs trace:read.
func ownHours(month: String) async throws -> OwnHours
/// When trips start in a month, all partners together: road load by weekday and hour (PLAN.md 18, 19). `month` is
/// YYYY-MM (Ulaanbaatar), published 14 days after it ends (400 month_open before). A weekday and hour shows only
/// under the trip cells rule; no slot means too few, not zero. No total. Needs insights:read.
func allHours(month: String) async throws -> AllHours
/// Where and when trips end in a month, all partners together: trips per khoroo and Ulaanbaatar hour of arrival
/// (PLAN.md 18, 19). `month` is YYYY-MM (Ulaanbaatar), published 14 days after it ends (400 month_open before). A
/// khoroo and hour shows only under the trip cells rule; no hour means too few, not zero. No khoroo total. Current
/// khoroo polygons only. Needs insights:read.
func traceKhoroos(month: String) async throws -> TraceKhoroos
/// Your organization's own trips per khoroo and Ulaanbaatar hour of arrival in a month: your dashboard (PLAN.md 18,
/// 20.13). `month` is YYYY-MM (Ulaanbaatar), an open month too; `closed` once final. No group rule. Each trip counts
/// once: in one khoroo, or in `noKhoroo` where no current khoroo polygon holds its end. Needs trace:read.
func ownKhoroos(month: String) async throws -> OwnKhoroos
/// Your organization's own trips per kind of building at the trip end in a month: what kind of deliveries you make
/// (PLAN.md 18, 20.13). `month` is YYYY-MM (Ulaanbaatar), an open month too; `closed` once final. No group rule. Each
/// trip counts once, by the building type when it was stored; `unknown` is a building with no type, `none` no building
/// within 30 m. Needs trace:read.
func ownKinds(month: String) async throws -> OwnKinds
/// Point to the places at and around it, nearest first. Needs geocode:read. `types` (API 0.69.0, Mapbox's types):
/// only these kinds, chosen before the limit, so limit doors are the nearest doors; sent once each, in the order
/// given. nil or empty: every kind.
/// `point` is sent as lon and lat; the API reads lng as lon too, for a hand-written request.
func reverse(_ point: LonLat, radius: Double? = nil, limit: Int? = nil, types: [ReverseType]? = nil) async throws -> ReverseResponse
/// Places of these categories near a point, nearest first, each with its category and distance (API 0.80.0). Needs
/// geocode:read. A chip such as "Эмийн сан" is [.pharmacy], "Хоол" [.restaurant, .cafe]. radius in metres, 1000
/// when nil, at most 10000; limit 10 when nil, at most 20. Categories are sent once each, in the order given; none
/// is refused here with the API's 400 invalid_category: no request. A store comes with code nil: show "код алга".
/// `point` is sent as lon and lat; the API reads lng as lon too, for a hand-written request.
/// `open` true sends open=1: only places open now; those with no readable hours are counted in hoursUnknown.
func nearby(_ point: LonLat, categories: [NearbyCategory], radius: Double? = nil, limit: Int? = nil, open: Bool = false, photo: Bool = false) async throws -> NearbyResponse
/// The building entrances nearest a point, nearest first, each with its building and distance (API 0.85.0): for a
/// long-press on the map or "Энд байгаа хаалга" from the user's position. Generated entrances count (source generated,
/// confidence 0: show them as таамаг). radius in metres, 50 when nil, at most 1000; limit 1 when nil, at most 20.
/// Needs geocode:read. `point` is sent as lon and lat; the API reads lng as lon too, for a hand-written request.
func entrancesNear(_ point: LonLat, radius: Double? = nil, limit: Int? = nil) async throws -> NearEntrances
/// The organizations registered in a building, by floor, for "Энд байгаа байгууллагууд" on an office building or
/// mall card. The id is a building's, from geocode, reverse or the building tile, or its unit code (a хашаа code
/// answers an empty list). Only organizations matched to an
/// official registration are listed; a floor or unit the register does not give is nil. Needs geocode:read.
/// 410 retired, 404 not_found (unknown, not a building, or restricted).
func directory(_ buildingId: String) async throws -> BuildingDirectory
/// A door from its 5-character code. Cyrillic lookalike keys are accepted. `unit` is the flat or office typed
/// after the code ("7QSVX 17"). Needs door:read. 404 not_found, 410 retired_code, 400 invalid_code.
/// A text that cannot be a code (parseDoorCode) is refused here with the API's 400 invalid_code: no request.
func door(_ code: String, unit: String? = nil) async throws -> Door
/// Register a spoken name for one of your doors ("Сансар бэйкери" for 7QSVX), held for a year (API 0.52.0). Your
/// own name with another code moves to that door. Needs names:write and the door_names feature (403 feature_off
/// until dock opens it for your organization). 409 name_taken, 410 retired_code, 404 not_found, 422 too_many.
@discardableResult func registerDoorName(_ name: String, code: String) async throws -> DoorNameReceipt
/// Your organization's door names, A to Z, expired ones flagged until another organization takes them. Needs
/// names:write.
func doorNames() async throws -> OwnDoorNames
/// The door a name names, as door(_:) answers it, official address first. Any spelling of the name finds it.
/// Needs door:read and the door_names feature. 404 not_found counts against the door miss cap. A name the API
/// would refuse (no letter, a phone number or an e-mail) is refused here with its 400: no request.
func doorByName(_ name: String) async throws -> NamedDoor
/// A one-time code that lets another organization claim one of your names (API 0.53.0). Shown once; a new one
/// replaces the old. Works for 7 days, or until the name expires if sooner. Needs names:write.
func doorNameTransferCode(_ name: String) async throws -> DoorNameTransfer
/// Clears the waiting transfer code of one of your names. `cancelled` is false when none was waiting. Needs
/// names:write.
@discardableResult func cancelDoorNameTransfer(_ name: String) async throws -> DoorNameTransferCancel
/// Take a name with the transfer code its holder gave you. The door and expiresAt stay; the code is used up;
/// status is transferred. Needs names:write. 409 transfer_refused (wrong, cleared or timed out; counts a door
/// miss), 409 already_yours, 422 too_many.
@discardableResult func claimDoorName(_ name: String, transferCode: String) async throws -> DoorNameReceipt
/// Write how guests find the entrance of the door one of your names points at, in mn, en or both (API 0.58.0).
/// The note waits for a person to review it; door(_:) serves the notes the map holds until then. Writing again
/// replaces your waiting text. Needs names:write and the hotel.notes feature (403 feature_off until dock opens it).
/// 400 personal_data for a phone number or e-mail in a note, invalid_notes, invalid_body; 404 not_found for a name
/// your organization does not hold. A name the API would refuse is refused here with its 400: no request.
@discardableResult func writeDoorNotes(_ name: String, instructionsMn: String? = nil, instructionsEn: String? = nil) async throws -> DoorNoteReceipt
/// Your notes for the door one of your names points at, each waiting, accepted or refused (API 0.59.0). Never
/// another organization's. Needs names:write and the hotel.notes feature; 404 not_found as for writeDoorNotes.
func doorNotes(_ name: String) async throws -> DoorNotes
/// Send a gate photo of the door one of your names points at: the entrance as a guest sees it (API 0.60.0). One
/// JPEG, up to 2 MB, 320 to 8000 px a side, sent as is. Its metadata is removed before it is stored; the
/// orientation stays. It waits for a person to review it; sending again replaces your waiting photo. Needs
/// names:write and the hotel.notes feature (403 feature_off until dock opens it). 400 not_jpeg, invalid_photo,
/// photo_too_small, photo_too_big; 413 too_large; 404 not_found for a name your organization does not hold. A name
/// the API would refuse is refused here with its 400: no request.
@discardableResult func sendDoorPhoto(_ name: String, jpeg: Data) async throws -> DoorPhotoReceipt
/// Your accepted gate photo for the door one of your names points at, the newest one a person accepted (API
/// 0.61.0). Never a waiting or refused one, never another organization's. Show it inside your app only, never on a
/// public page. Pass the sha256 of the photo you hold: when it is still the one served, jpeg is nil and no bytes
/// come. A sha256 that is not 64 hex characters is not sent; the photo then comes whole. 404 not_found for a name
/// your organization does not hold, a retired door, a restricted site or no accepted photo. Needs names:write and
/// the hotel.notes feature. A name the API would refuse is refused here with its 400: no request.
func doorPhoto(_ name: String, sha256: String? = nil) async throws -> DoorPhoto
/// One end of a route: a building code (routes to its street side or gate) or a point.
enum End: ExpressibleByExtendedGraphemeClusterLiteral, ExpressibleByStringLiteral, ExpressibleByUnicodeScalarLiteral, Sendable {
/// A building code, as typed: the route ends at the street side or the gate.
case code(String)
/// A point.
case point(LonLat)
/// A string literal is a building code: `route(from: "7QSVX", to: ...)`.
init(stringLiteral value: String)
}
/// Route between two ends. A code routes to the street side of its building or the gate of its yard; `to.gapM` is the walk left from the road.
/// Needs route:read, and door:read for a code. 422 no_route, end_in_closure (an end inside a closure active
/// today; closure(at:) checks offline), closures_over_limit, 404 not_found. departAt (API 0.50.0): a driving
/// route's measured reads the speeds of its hour band; sent in UTC. via (API 0.67.0): up to routeViaMax ends passed
/// on the way, in order; the answer has one leg per hop and each via end where the line passes it. An empty list is
/// none. A long list, or a code holding ";", is refused here with the API's 400 invalid_via: no request. 404
/// not_found names a via end by its place ("via[1]: ...").
func route(from: End, to: End, via: [End] = [], mode: RouteMode? = nil, departAt: Date? = nil) async throws -> Route
/// Free-flow time and distance from every end in `from` to every end in `to`, in one call (API 0.63.0): up to
/// matrixMax by matrixMax, each end a building code or a point as in route. `durationsS[i][j]` goes from `from[i]` to
/// `to[j]`; nil where no path joins them. Needs route:read, and door:read for a code. An empty or long list, or a
/// code holding ";", is refused here with the API's 400 invalid_from or invalid_to: no request. 404 not_found names
/// the end by its place ("to[1]: ..."); 422 no_route, end_in_closure, closures_over_limit as for route.
func matrix(from: [End], to: [End], mode: RouteMode? = nil) async throws -> Matrix
/// The area reached from one end within each of `contoursMinutes` (API 0.64.0), as a GeoJSON FeatureCollection:
/// one Polygon or MultiPolygon per contour, the largest first. `from` is a building code (from its street side or gate) or a point
/// as in route. 1 to isochroneContoursMax whole minutes from 1 to isochroneMinutesMax, increasing; anything else is
/// refused here with the API's 400 invalid_contours: no request. Needs route:read, and door:read for a code. 404
/// not_found; 422 no_route (no road near from), end_in_closure, closures_over_limit, not_accepted as for route.
func isochrone(from: End, contoursMinutes: [Int], mode: RouteMode? = nil) async throws -> Isochrone
/// A GPS trace matched to the road network (API 0.65.0): the roads it went along, one matching per unbroken piece,
/// and one tracepoint per point, nil where no road was found or the point is in a restricted site. `coordinates` is 2
/// to matchingMax points in the order recorded; `timestamps`, optional, one whole Unix second per point, never going
/// back. Anything else is refused here with the API's 400 invalid_coordinates or invalid_timestamps: no request.
/// Needs route:read. 422 no_match (no road near the trace), not_accepted (fewer than 2 points outside restricted
/// sites). Closures are not avoided. The API neither stores nor logs the trace; to share a trip, use startTrace.
func matching(_ coordinates: [LonLat], timestamps: [Int]? = nil, mode: RouteMode? = nil) async throws -> Match
/// The order to visit stops in with the least time on the road, and the trip in that order (API 0.66.0). `stops` is
/// 2 to optimizedTripsMax ends, each a building code (to its street side or gate) or a point as in route; the trip starts at the
/// first. `roundtrip` true, the API's default, goes back to it; false ends at the last sent. `waypoints` are the
/// stops in the order sent, each with `waypointIndex`, its place in the trip. A short or long list, or a code
/// holding ";", is refused here with the API's 400 invalid_coordinates: no request. Needs route:read, and door:read
/// for a code. 404 not_found names the stop by its place ("coordinates[1]: ..."); 422 no_route (a stop no road
/// reaches), not_accepted, end_in_closure, closures_over_limit as for route. Free-flow times, no time at the stops.
func optimizedTrips(_ stops: [End], roundtrip: Bool? = nil, mode: RouteMode? = nil) async throws -> OptimizedTrip
/// The buildings and entrances at or near a point (API 0.68.0), as Mapbox's Tilequery API: what a tap on the map
/// is on. `sources` is building, entrance or place, each once; the default is building and entrance. `radius` in metres, 0 to
/// tilequeryRadiusMaxM, sent to the centimetre; nil or 0, the API's default, finds the building the point is inside,
/// and an entrance needs a radius. `limit` 1 to tilequeryLimitMax, the API's default 5. `geometry` keeps one type.
/// GeoJSON, nearest first: each feature the Point of it nearest the point sent, its tile fields and `tilequery`
/// (distance in metres, geometry, layer). No building codes: door(_:unit:) takes a code. Anything the API would refuse
/// is refused here with its error: 404 not_found (sources), 400 invalid_point, invalid_radius, invalid_limit; no
/// request. Needs tiles:read; counts against rate_limit and daily_quota. Coverage: Ulaanbaatar.
func tilequery(_ point: LonLat, sources: [TilequerySource] = [.building, .entrance], radius: Double? = nil, limit: Int? = nil, geometry: TilequeryGeometry? = nil) async throws -> Tilequery
/// Road closures not over today (PLAN.md 20.14), each with the ring Valhalla avoids. No partner name, no note.
/// Keep the answer for offline use; excludePolygons(_:day:) picks the rings for a route day. idsSha256 changes
/// when a closure is added or lifted. Needs route:read.
func closures() async throws -> ClosuresResponse
/// Report a stretch or a crossing that cannot be driven (PLAN.md 20.14). Kept forever: never edited or deleted, lift
/// it when the road opens. Needs closures:write. Pass `idempotencyKey` (UUID().uuidString fits), and the same key and
/// report when you retry after a timeout: the API answers the first report and stores nothing twice; the same key
/// with another report is 422 idempotency_key_reused. A key the API would refuse is refused here with its 400
/// bad_idempotency_key: no request. 400 note_has_phone, outside_mongolia, line_too_long, restricted and the rest
/// come from the API.
func reportClosure(_ report: ClosureReport, idempotencyKey: String? = nil) async throws -> Closure
/// One of your organization's closure reports as stored, note included: your export. Needs closures:write.
/// 404 not_found for others' ids.
func closure(_ id: String) async throws -> Closure
/// The road is open again: lift one of your reports from `on` (YYYY-MM-DD Ulaanbaatar), nil for today, never a
/// later day (400 lift_in_future) nor before its from (400 lift_before_from). Lifting twice keeps the first day.
/// Needs closures:write.
@discardableResult func liftClosure(_ id: String, on: String? = nil) async throws -> Closure
/// Tell dock a door is wrong. A person reviews it; door data does not change until then. Needs door:read.
func reportDoor(_ report: DoorReport) async throws -> DoorReportReceipt
/// One place again, by the id geocode, reverse or changes gave: the place fields plus `parents`. Needs
/// geocode:read. 410 retired (the id is never reused), 404 not_found.
func place(_ id: String) async throws -> Address
/// Ids of places changed in [since, until), oldest first, one page. Needs changes:read (partner keys). Pass the
/// page's `next` as `cursor` until it is nil, then poll again with since = until. First sync: since
/// Date(timeIntervalSince1970: 0). limit 1 to 1000, default 100, on every call: the cursor does not keep it.
func changes(since: Date?, limit: Int? = nil, cursor: String? = nil) async throws -> ChangesResponse
/// A driver on site says a door is there, elsewhere or gone. Needs confirm:write (partner keys). Map data does
/// not change at once. 422 implausible when device is over 40 m from the tap, too_far when the tap is over 500 m
/// from the entrance: ask the driver to tap again on site.
func confirm(_ confirmation: Confirmation) async throws -> ConfirmReceipt
/// Your drivers' confirmations and door reports in a month: your dashboard (PLAN.md 18). `month` is YYYY-MM
/// (Ulaanbaatar). Counts by result for the month and each day on site, different drivers (never the ids), and up to
/// 100 failure points. The month you are in is answered too; `closed` is true from 8 days after it ends. No other
/// organization is read. Needs confirm:read, a read-only scope: confirm:write does not read it.
func ownConfirmations(month: String) async throws -> OwnConfirmations
/// This key's organization: caps and the last `days` days (1 to 90). Free, answers after the quota.
func usage(days: Int? = nil) async throws -> UsageResponse
/// TileJSON URL of a tile source (building, entrance), without the key.
func tileJSONURL(_ source: String) -> URL
/// Adds the key to a URL of this API only, as ?access_token=. Other hosts (a partner basemap, fonts) get nothing.
/// Use it where MapLibre Native asks for a resource URL.
func authorizedURL(_ url: URL) -> URL
/// The dock style as MapLibre style JSON, both tile sources keyed. Holds the key: never log it.
func styleJSON(_ options: StyleOptions = StyleOptions()) -> String
/// A style saved in the style editor, keyed, for MLNMapView's styleURL. Throws StyleError.badStyleId.
func styleURL(_ styleId: String) throws -> URL
/// A building with an indoor map: outline and floors. `venueId` is the `indoor.venue_id` a geocode row carries.
/// Needs door:read. 404 not_found for an unknown id.
func venue(_ venueId: String) async throws -> Venue
/// One floor of a venue as GeoJSON: its units, openings and amenities, each with source and confidence. `level`
/// is the floor number (0 ground, -1 basement). Needs door:read. 404 not_found for an unknown venue or floor.
func venueLevel(_ venueId: String, level: Int) async throws -> VenueLevel
/// What a printed plate for one unit says: venue, floor, name or number, a point, and the link its QR holds.
/// `unitId` is a unit's id from venueLevel. Needs door:read. 404 not_found for an unknown venue or unit.
func venueSpot(_ venueId: String, unitId: String) async throws -> VenueSpot
/// The walk inside a venue to one unit, floor by floor, with steps in Mongolian and the floor on each. `from`
/// is a point on floor `fromLevel` (0 when nil): the entrance a road route used, or a tapped spot. Needs
/// door:read. 404 not_found; 422 no_route where no drawn corridor joins the start and the unit.
func venueRoute(_ venueId: String, from: LonLat, unitId: String, fromLevel: Int? = nil) async throws -> VenueRoute
/// The whole way to a unit in one answer: the road to the right street entrance, then the walk inside. `mode`
/// is driving when nil. Needs route:read. 404 not_found; 422 no_entrance when no street entrance is drawn, 422
/// no_route when no road or no corridor reaches it.
func venueDirections(_ venueId: String, from: LonLat, unitId: String, mode: RouteMode? = nil) async throws -> VenueDirections
}Closures.swift
swift
/// Valhalla's exclude_polygons limits per route request, all rings together (GET /v1/closures).
struct ValhallaLimits: Codable, Equatable, Sendable {
let perimeterM: Double
let vertices: Int
}
/// One closure in GET /v1/closures. No partner name, no note.
struct ClosureItem: Codable, Equatable, Sendable {
/// cl-000001. Never reused.
let id: String
/// flood, washout, bridge_out, snow, mud, works or other.
let kind: String
/// First closed day, YYYY-MM-DD Ulaanbaatar.
let from: String
/// Last closed day, or nil: until lifted.
let to: String?
/// One partner's word, not field checked.
let confidence: Double
let perimeterM: Double
/// Ring vertices, the closing one included.
let vertices: Int
/// Closed ring. One of Valhalla's exclude_polygons.
let ring: [LonLat]
/// from <= day, and day <= to when to is set. Days compare as YYYY-MM-DD strings.
func isActive(on day: String) -> Bool
}
/// GET /v1/closures: every closure not over today, the same shape as an offline pack's closures block.
struct ClosuresResponse: Codable, Equatable, Sendable {
let method: String
let source: String
/// Today when it was fetched, YYYY-MM-DD Ulaanbaatar.
let asOf: String
let current: Int
/// sha256 of the sorted ids joined by commas; nil for none. An offline pack's closures_sha256.
let idsSha256: String?
let bufferM: Double
let rule: String
let activeWhen: String
/// Per route request, all rings together.
let valhallaLimits: ValhallaLimits
let items: [ClosureItem]
}
/// What to send Valhalla for one route day: the rings of the closures active that day.
struct ExcludePolygons: Equatable, Sendable {
/// YYYY-MM-DD, Ulaanbaatar.
let day: String
/// The closures avoided, in list order. Show them with the route.
let ids: [String]
/// Valhalla's exclude_polygons.
let rings: [[LonLat]]
let perimeterM: Double
let vertices: Int
/// Offline: the id of the first closure here whose ring holds `point`, or nil. Valhalla drops every road inside an
/// exclude ring, so a route from or to that point has no road to start from: it answers "No path could be found
/// for input". Check both ends before asking your own Valhalla, as GET /v1/route does (422 end_in_closure).
func closure(at point: LonLat) -> String?
}
/// What excludePolygons(_:day:) and packRoute throw.
enum ClosuresError: CustomStringConvertible, Equatable, Error, Sendable {
/// Not a calendar day as YYYY-MM-DD.
case badDay(String)
/// Closures that ended before as_of are not in the list: fetch again.
case beforeAsOf(day: String, asOf: String)
/// The day's closures are over Valhalla's limits for one request. Refuse the route: never drop a closure.
case overLimit(day: String, count: Int, perimeterM: Double, vertices: Int)
var description: String { get }
}
/// Today in Ulaanbaatar (UTC+8, no daylight saving), YYYY-MM-DD.
func ubToday(_ now: Date = Date()) -> String
/// Offline: the rings to send Valhalla as exclude_polygons for a route on `day` (default today, Ulaanbaatar), from a
/// GET /v1/closures answer or an offline pack's closures block. Throws badDay, beforeAsOf (fetch again), or overLimit
/// over Valhalla's limits.
func excludePolygons(_ closures: ClosuresResponse, day: String = ubToday()) throws -> ExcludePolygons
/// What is closed, in a report (POST /v1/closures).
enum ClosureKind: CaseIterable, Codable, Equatable, Hashable, RawRepresentable, Sendable {
case flood
case washout
case bridgeOut
case snow
case mud
case works
case other
}
/// A closure's place: a point on the stretch (not on a junction), or a line of 2 or more points, at most 3000 m.
enum ClosureGeometry: Codable, Equatable, Sendable {
case point(LonLat)
case lineString([LonLat])
init(from decoder: Decoder) throws
func encode(to encoder: Encoder) throws
}
/// POST /v1/closures. The sender is the key's organization.
struct ClosureReport: Encodable, Equatable, Sendable {
var geometry: ClosureGeometry
var kind: ClosureKind
/// First closed day, YYYY-MM-DD Ulaanbaatar. nil: today.
var from: String?
/// Last closed day. nil: until lifted.
var to: String?
/// Your words for your own records, at most 200 characters; never served to others. No names, no phone numbers.
var note: String?
init(geometry: ClosureGeometry, kind: ClosureKind, from: String? = nil, to: String? = nil, note: String? = nil)
}
/// A closure's fields, in Closure.properties.
struct ClosureProperties: Codable, Equatable, Sendable {
/// flood, washout, bridge_out, snow, mud, works or other.
let kind: String
let from: String
let to: String?
/// Open again from this day, YYYY-MM-DD; set once. nil: not lifted.
let lifted: String?
/// As sent; "" for none.
let note: String
let confidence: Double
/// UTC ISO 8601.
let reportedAt: String
}
/// One of your organization's closure reports, as stored (reportClosure, closure(_:), liftClosure).
struct Closure: Codable, Equatable, Sendable {
/// "Feature".
let type: String
/// cl-000001. Never reused.
let id: String
let geometry: ClosureGeometry
let properties: ClosureProperties
}
/// The API's Idempotency-Key rule (api/src/modules/closures/closure-input.ts IDEM_KEY).
let idempotencyKeyPattern: String
/// 1 to 64 of A-Z a-z 0-9 . _ : -, as idempotencyKeyPattern. Checked by byte: a regex $ would pass a final newline.
func isValidIdempotencyKey(_ key: String) -> BoolCode.swift
swift
/// Digits and consonants: no vowels, no I, L, O, U.
let doorCodeAlphabet: String
/// Characters in a building code.
let doorCodeLength: Int
/// Why a text cannot be a building code.
enum DoorCodeError: Equatable, Hashable, RawRepresentable, Sendable {
/// Nothing typed.
case empty
/// Not 5 characters.
case length
/// A character no code uses (a vowel, I, L, O, U, a Cyrillic letter with no Latin twin, a sign).
case letters
}
/// What parseDoorCode read.
enum DoorCodeInput: Equatable, Sendable {
/// The code, upper case Latin, and whatever followed it (flat number, household name) as typed, or nil.
case code(String, unit: String?)
/// `reason` is the API's invalid_code message, in English; show the person your own words for `error`.
case invalid(DoorCodeError, reason: String)
}
/// Reads a typed or pasted building code as the API would: "7QSVX", "7qsvx 17", "7QSVХ Бат". No request. Use it to
/// check a field as the person types, and send only `.code` to door(): a code that finds no door counts against
/// the daily miss cap; one that cannot be a code is caught here first.
func parseDoorCode(_ text: String) -> DoorCodeInput
/// A door link (PLAN.md 4a: "send the code, a link, or a QR"; PLAN 18 entry paths 1 and 4): this base, the code,
/// and `?u=` with the unit when there is one. sdk/testdata/door-link.json holds the cases the three SDKs agree on.
let doorLinkBase: String
/// The link to a door, for a share sheet, a message or a QR: "https://map.dock.mn/d/7QSVX?u=17". `text` and `unit`
/// are read as parseDoorCode reads `text unit`, so the code may be typed in Cyrillic lookalikes and the unit (flat
/// number, household name) goes in percent-encoded. nil when the text cannot be a code. No request: the link says
/// nothing about whether a door has this code.
func doorLink(_ text: String, unit: String? = nil) -> String?
/// Reads the first door link in a text: a pasted link, a share message with a link in it, or the URL a universal
/// link opened the app with. http or https or none, the host in any case, `?u=` for the unit, other parameters and
/// `#` ignored. nil when the text has no door link; otherwise what parseDoorCode reads from the code and the unit,
/// so a link with a broken code is `.invalid` with the same reasons. No request.
func parseDoorLink(_ text: String) -> DoorCodeInput?Crossings.swift
swift
/// Modelled monthly flow at a river crossing (lane D's dock_steppe.rivers). Rivers only: streams have none.
struct CrossingFlow: Codable, Equatable, Sendable {
let riverId: Int
/// 1991 to 2020 monthly normals, January to December, m3/s.
let normalM3s: [Double]
/// Months 1 to 12 whose normal is at least 1.5 times the mean of the 12.
let highMonths: [Int]
/// agrees, doubtful (the model reach is 10x below its OSM river's), unchecked.
let reach: String
/// 0.4, or lowFlowConfidence (0.1) on a doubtful reach and on snap none_fits or main_stem.
let confidence: Double
/// How the reach was picked. matched: it follows the OSM river. none_fits: none does, the nearest is kept.
/// main_stem: the channel follows only a small reach, the river's main stem is taken. nearest: the nearest, no
/// lines to match on. nil in packs built before the match.
let snap: String?
}
/// A delta channel: the river splits into a lake there and no model reach says what share a channel carries. The
/// crossing has no flow. Rule text in the pack's flow.delta.rule and rule_mn.
struct CrossingDelta: Codable, Equatable, Sendable {
/// The lake's OSM name, folded to one script when it mixed Latin and Cyrillic in a word.
let lake: String?
/// The lake's OSM name as written, when lake is folded. nil when lake is the OSM text, and in packs before national
/// crossings v11. Show lake.
let lakeNameOsm: String?
/// The lake's OSM element, as relation/114846.
let lakeOsm: String
/// The river whose mouths form the delta.
let river: String
}
/// An unnamed river or stream whose two ends lie on one named OSM river: a channel of it. From the OSM drawing, not
/// checked on the ground. Rule text in the pack's channel_rule and channel_rule_mn.
struct CrossingChannelOf: Codable, Equatable, Sendable {
/// The river's OSM name, as on its riverWayId way.
let name: String
let nameEn: String?
/// The OSM way the name was read from.
let riverWayId: Int64
}
/// An unnamed river or stream, not a channel, and the named OSM river its water reaches downstream by the direction the
/// ways are drawn. From the OSM drawing, not checked on the ground. Rule text in the pack's tributary_rule and
/// tributary_rule_mn.
struct CrossingFlowsInto: Codable, Equatable, Sendable {
/// The river's OSM name, as on its riverWayId way.
let name: String
let nameEn: String?
/// The OSM way the name was read from.
let riverWayId: Int64
/// The fewest unnamed ways from this crossing's way to the river, its own included.
let ways: Int
}
/// The OSM tags of the route ways at a crossing. Rule text in the pack's road_rule and road_rule_mn.
struct CrossingRoad: Codable, Equatable, Sendable {
/// The ways' OSM highway tags, as track or trunk.
let highway: [String]
/// The ways' OSM surface tags; empty when none has one.
let surface: [String]
/// true: a way has a paved surface. false: every way has an unpaved one. nil: a way has no surface tag. A none
/// crossing on a paved road may be a bridge or culvert OSM does not tag; not checked.
let paved: Bool?
}
/// At or under this flow confidence the model reach is not sure to be this river's: show the months, not the m3/s.
let lowFlowConfidence: Double
/// A GeoJSON Point: type "Point" and [lon, lat]. The geometry of a crossing, a pass or a place in a pack.
struct CrossingGeometry: Codable, Equatable, Sendable {
let type: String
let coordinates: LonLat
}
/// A crossing's fields, in CrossingFeature.properties.
struct CrossingProperties: Codable, Equatable, Sendable {
/// ford: OSM says ford. none: OSM has no bridge or ford there, not that there is none.
let kind: String
/// river, stream, canal, or unknown on a ford node with no waterway line (fordNodeId set).
let waterway: String
let name: String?
/// The OSM name as written, when it mixed Latin and Cyrillic in a word and name is folded to one script. nil when
/// name is the OSM text. Show name. Packs before offline v13 lack it.
let nameOsm: String?
let nameEn: String?
let intermittent: Bool
/// nil for streams and canals, and in packs built before the flow block.
let flow: CrossingFlow?
/// Set on a delta channel, with flow nil. nil in packs built before the delta rule.
let delta: CrossingDelta?
/// Set on an unnamed channel of a named river. nil in packs built before the channel rule.
let channelOf: CrossingChannelOf?
/// Set on an unnamed river or stream that reaches one named river. nil in packs built before the tributary rule.
let flowsInto: CrossingFlowsInto?
/// nil on a new track alone (no OSM way), and in packs built before the road rule.
let road: CrossingRoad?
/// The OSM ford node, on a ford whose water OSM does not draw as a line; waterway is unknown. nil on line crossings
/// and in packs built before the ford node rule.
let fordNodeId: Int64?
}
/// One crossing point in an offline pack's crossings.geojson (files[1]).
struct CrossingFeature: Codable, Equatable, Sendable {
let type: String
let geometry: CrossingGeometry
let properties: CrossingProperties
}
/// The pack's flow block: the attribution to show with a high water month.
struct CrossingsFlowBlock: Codable, Equatable, Sendable {
let attribution: String
}
/// An offline pack's crossings.geojson. Check its sha256 against the manifest's files[1] before use.
struct PackCrossings: Codable, Equatable, Sendable {
let type: String
/// A route passes a crossing when its line comes this close, m.
let matchM: Double
let note: String
let noteMn: String
/// nil in packs built before the flow block.
let flow: CrossingsFlowBlock?
let features: [CrossingFeature]
/// Crossings with road.paved true. nil in packs built before the road rule, as the two rule texts.
let onPaved: Int?
let roadRule: String?
let roadRuleMn: String?
/// None crossings that became the crossing of a bridge drawn just off the water, so left out of the pack. nil in
/// packs built before the bridge rule, as the two rule texts.
let nearBridge: Int?
let bridgeRule: String?
let bridgeRuleMn: String?
/// Crossings joined into the one beside them because their water way is split into two ways at the road. nil in
/// packs built before the split rule, as the two rule texts.
let onePoint: Int?
let splitRule: String?
let splitRuleMn: String?
/// Crossings marked intermittent from OSM seasonal=* alone, no intermittent tag. nil in packs built before that
/// rule, as the two rule texts.
let fromSeasonal: Int?
let intermittentRule: String?
let intermittentRuleMn: String?
/// Fords from an OSM ford node alone, no waterway line drawn. nil in packs built before that rule, as the two rule
/// texts.
let fordNodes: Int?
let fordNodeRule: String?
let fordNodeRuleMn: String?
/// Names in the file folded to one script, all Mongolia, and the rule, en and mn. nil in packs before offline v13.
let namesFolded: Int?
let nameRule: String?
let nameRuleMn: String?
/// The file's bytes, as in the pack.
init(json: Data) throws
}
/// A ford or unbridged crossing the route passes.
struct CrossingWarning: Equatable, Sendable {
/// ford or none.
let kind: String
let point: LonLat
let waterway: String
let name: String?
/// The OSM text when name was folded to one script, else nil. Show name.
let nameOsm: String?
let nameEn: String?
let intermittent: Bool
/// Along the route to its point nearest the crossing, m, rounded. A tie goes to the earlier pass.
let alongM: Double
/// From the route line, m, one decimal.
let offM: Double
/// The month is one of highMonths. nil when the crossing has no flow (streams, canals).
let highWater: Bool?
let highMonths: [Int]
/// The month's normal, m3/s. nil with no flow, on a doubtful reach, and at lowFlowConfidence or under (snap
/// none_fits, main_stem): show the months, not the number.
let monthM3s: Double?
let reach: String?
let confidence: Double?
/// The flow's snap. nil with no flow or in a pack built before the match.
let snap: String?
/// A delta channel: say "delta channel, flow unknown". nil elsewhere and in packs built before the delta rule.
let delta: CrossingDelta?
/// An unnamed channel of a named river: say "unnamed channel of <name>". nil elsewhere and in packs built before
/// the channel rule.
let channelOf: CrossingChannelOf?
/// An unnamed river or stream that reaches a named river: say "unnamed, flows into <name>". channelOf wins when
/// both are set. nil elsewhere and in packs built before the tributary rule.
let flowsInto: CrossingFlowsInto?
/// The road the route crosses on. With kind none and paved true, say "paved road, OSM tags no bridge here". nil on
/// a new track alone and in packs built before the road rule.
let road: CrossingRoad?
/// The OSM ford node of a ford whose water OSM does not draw as a line, waterway unknown: say "OSM ford, water not
/// drawn". nil on line crossings and in packs built before the ford node rule.
let fordNodeId: Int64?
}
/// What crossingsOnRoute(_:line:month:) returns: the warnings in route order, with the pack's note.
struct RouteCrossings: Equatable, Sendable {
/// 1 to 12.
let month: Int
let matchM: Double
/// In route order.
let warnings: [CrossingWarning]
/// Show with the warnings: from OSM tags, not field checked.
let note: String
let noteMn: String
/// Show when a warning has flow; else nil.
let flowAttribution: String?
/// How the pack folds a name that mixes Latin and Cyrillic, en and mn. nil when the pack has no rule.
let nameRule: String?
let nameRuleMn: String?
}
/// What crossingsOnRoute(_:line:month:) throws.
enum CrossingsError: CustomStringConvertible, Equatable, Error, Sendable {
/// A route line needs at least 2 points.
case shortLine(Int)
/// Not 1 to 12.
case badMonth(Int)
var description: String { get }
}
/// This month in Ulaanbaatar (UTC+8), 1 to 12. crossingsOnRoute's default month.
func ubMonth(_ now: Date = Date()) -> Int
/// Offline: the ford and unbridged crossings a route line passes, from an offline pack's crossings.geojson, in route
/// order. `month` (1 to 12, default this month in Ulaanbaatar) sets highWater. Throws CrossingsError for a line under
/// 2 points or a bad month.
func crossingsOnRoute(_ crossings: PackCrossings, line: [LonLat], month: Int = ubMonth()) throws -> RouteCrossingsDoorNames.swift
swift
/// A door name your organization holds, as POST /v1/door-names and the claim answer it.
struct DoorNameReceipt: Codable, Equatable, Sendable {
/// As registered, spaces collapsed.
let name: String
/// The door it names.
let code: String
let registeredAt: String
/// After this the name finds nothing and any organization may take it.
let expiresAt: String
/// registered: yours from now. moved: your name now names this door. unchanged: it already did. A claim answers
/// transferred.
let status: String
}
/// One of your organization's names in doorNames().
struct OwnDoorName: Codable, Equatable, Sendable {
let name: String
let code: String
let registeredAt: String
let expiresAt: String
/// true after expiresAt: it finds nothing, and stays listed until another organization takes it.
let expired: Bool
/// When the transfer code you made stops working (API 0.53.0); nil when none is waiting.
let transferUntil: String?
}
/// GET /v1/door-names: your organization's names, A to Z.
struct OwnDoorNames: Codable, Equatable, Sendable {
/// Unexpired names one organization may hold at once.
let limit: Int
let names: [OwnDoorName]
}
/// GET /v1/door-names/{name}: the door as door(_:) answers it, official address first. The holder is never shown.
struct NamedDoor: Codable, Equatable, Sendable {
let name: String
let expiresAt: String
let door: Door
}
/// POST /v1/door-names/{name}/transfer-code. The code is shown once, never again.
struct DoorNameTransfer: Codable, Equatable, Sendable {
let name: String
/// dnt_ and 24 characters. Anyone holding it can claim the name: give it only to the organization taking it.
let transferCode: String
/// Refused after this: 7 days, or the name's expiresAt if sooner.
let transferUntil: String
}
/// DELETE /v1/door-names/{name}/transfer-code. cancelled: a waiting code was cleared; false: none was waiting.
struct DoorNameTransferCancel: Codable, Equatable, Sendable {
let name: String
let cancelled: Bool
}
/// POST /v1/door-names/{name}/notes (API 0.58.0, feature hotel.notes): your waiting note.
struct DoorNoteReceipt: Codable, Equatable, Sendable {
/// The waiting note; writing again keeps it.
let id: String
/// queued: a new note waits for review. updated: your waiting note has this text now. unchanged: it had.
let status: String
let name: String
/// The door the name points at, which the note is for.
let code: String
let instructionsMn: String?
let instructionsEn: String?
/// When the waiting text was last written.
let receivedAt: String
/// review: a person reviews it. Until then door(_:) serves the notes the map holds, not this one.
let next: String
}
/// One of your notes in doorNotes(_:).
struct DoorNoteState: Codable, Equatable, Sendable {
let id: String
/// waiting: not reviewed, guests do not see it. accepted: door(_:) serves the languages it gave. refused: not used.
let state: String
let instructionsMn: String?
let instructionsEn: String?
/// When this text was last written.
let receivedAt: String
/// When a person accepted or refused it; nil while it waits.
let reviewedAt: String?
}
/// GET /v1/door-names/{name}/notes (API 0.59.0): your organization's notes for the door, never another's.
struct DoorNotes: Codable, Equatable, Sendable {
let name: String
/// The door the name points at now.
let code: String
/// The waiting one first, then the newest review, at most 20. Empty: you wrote none.
let notes: [DoorNoteState]
}
/// POST /v1/door-names/{name}/photo (API 0.60.0, feature hotel.notes): your waiting gate photo.
struct DoorPhotoReceipt: Codable, Equatable, Sendable {
/// The waiting photo; sending again keeps it.
let id: String
/// queued: a new photo waits for review. updated: your waiting photo is now this one. unchanged: it was.
let status: String
let name: String
/// The door the name points at, which the photo is for.
let code: String
/// SHA-256 of the photo as stored, after its metadata was removed: not the hash of the file you sent.
let sha256: String
/// Size as stored, in bytes.
let bytes: Int
/// Pixels as stored, before the EXIF orientation turns it.
let width: Int
let height: Int
/// When the waiting photo was last sent.
let receivedAt: String
/// review: a person reviews the photo. Once accepted, doorPhoto(_:sha256:) serves it.
let next: String
}
/// GET /v1/door-names/{name}/photo (API 0.61.0): your accepted gate photo, for your app only.
struct DoorPhoto: Equatable, Sendable {
/// SHA-256 of the photo served, lowercase hex: the receipt's sha256 once a person accepted it.
let sha256: String
/// The JPEG as stored, metadata removed, orientation kept. nil means unchanged: the photo you hold with this
/// sha256 is still the one served.
let jpeg: Data?
}Format.swift
swift
/// Language of a label.
enum Lang: Equatable, Hashable, RawRepresentable, Sendable {
case mn
case en
}
/// The spoken form, then the name, then the long form, then the code, each in `lang` first. Never the id.
/// Anything without a matched official address ends in "(албан бус)" / "(unofficial)": VISION rule 1, PLAN.md 4d.
func label(_ door: Door, lang: Lang = .mn) -> String
/// The same for the door at one end of a route: the spoken form, then the code.
func label(_ door: RouteDoor, lang: Lang = .mn) -> String
/// The same for a geocode result: the name, then the long form, then the code.
func label(_ place: GeocodeResult, lang: Lang = .mn) -> String
/// The same for a reverse result: the name, then the long form, then the code.
func label(_ place: ReverseResult, lang: Lang = .mn) -> String
/// The same for an address: the name, then the long form, then the code.
func label(_ place: Address, lang: Lang = .mn) -> StringPack.swift
swift
/// One row of an offline pack manifest's `files`: a file in the pack folder, its size and sha256.
struct PackFile: Codable, Equatable, Sendable {
let name: String
let bytes: Int
/// Lower case hex.
let sha256: String
init(name: String, bytes: Int, sha256: String)
}
/// The part of an offline pack's manifest.json checkPack reads.
struct PackManifestFiles: Codable, Equatable, Sendable {
let files: [PackFile]
init(files: [PackFile])
/// The whole manifest.json's bytes; only `files` is read.
init(json: Data) throws
}
/// ok: size and sha256 match. missing: no such file. bytes: another size, not hashed. sha256: same size, other bytes.
enum PackFileStatus: Equatable, Hashable, RawRepresentable, Sendable {
case ok
case missing
case bytes
case sha256
}
/// One file of a pack manifest as checkPack(_:directory:) found it.
struct PackFileCheck: Equatable, Sendable {
let name: String
let status: PackFileStatus
/// The file's size, nil when missing.
let bytes: Int?
let expectedBytes: Int
/// The file's sha256, nil when missing or another size.
let sha256: String?
let expectedSha256: String
}
/// What checkPack(_:directory:) returns.
struct PackCheck: Equatable, Sendable {
/// Every listed file is there with its size and sha256. Use no file from the pack otherwise.
let ok: Bool
/// In manifest order.
let files: [PackFileCheck]
/// Names of the files not ok, in manifest order. Download them again.
let bad: [String]
}
/// What checkPack(_:directory:) throws.
enum PackError: CustomStringConvertible, Equatable, Error, Sendable {
case noFiles
/// Not a plain file name: a folder, a leading dot, or empty.
case badName(String)
case listedTwice(String)
case badBytes(String, Int)
case badSha256(String, String)
var description: String { get }
}
/// Offline: checks each file the manifest lists in `directory`, in its order, by size and then sha256, reading 1 MB
/// at a time. A folder where a file is listed is missing. Files the manifest does not list are not read. Blocks while
/// it hashes (the base map is over 100 MB): call it off the main thread. Throws PackError for a manifest with no
/// files, a name that is not a plain file name, a name listed twice, a negative bytes value, or a sha256 that is not
/// 64 lower case hex; a file that cannot be read throws its own error.
func checkPack(_ manifest: PackManifestFiles, directory: URL) throws -> PackCheckPackRoute.swift
swift
/// What every route on a pack sends: costing auto, costing_options.auto.use_tracks 0.5 today. Keys as written.
struct PackRouteRequest: Codable, Equatable, Sendable {
let costing: String
/// Valhalla's costing_options, as in the manifest. nil when it has none.
let costingOptions: JSONValue?
init(costing: String, costingOptions: JSONValue? = nil)
}
/// The part of an offline pack's manifest.json packRoute reads.
struct PackRouteManifest: Equatable, Sendable {
let id: String
/// [west, south, east, north].
let bbox: [Double]
let request: PackRouteRequest
/// scored, or osm_only: no trace scores yet.
let confidence: String
/// What confidence means, for the driver, en and mn. Packs from offline v10; nil before.
let confidenceNote: String?
let confidenceNoteMn: String?
let attribution: String
let note: String
let closures: ClosuresResponse
init(id: String, bbox: [Double], request: PackRouteRequest, confidence: String, attribution: String, note: String, closures: ClosuresResponse, confidenceNote: String? = nil, confidenceNoteMn: String? = nil)
/// The whole manifest.json's bytes. costing_options keeps its keys as written (use_tracks).
init(json: Data) throws
}
/// What packRoute(_:stops:day:closures:) returns: the Valhalla request and what to show with the route.
struct PackRoute: Equatable, Sendable {
/// POST it to /route on your own Valhalla, the pack's tiles.tar as mjolnir.tile_extract: locations, costing,
/// costing_options, exclude_polygons, units km.
let body: JSONValue
/// The manifest's id.
let pack: String
let day: String
/// The closures the body avoids, in list order. Show them with the route.
let closures: [String]
/// The pack's route costs come from trace scores.
let scored: Bool
let confidence: String
/// What confidence means, for the driver: the manifest's confidenceNote and confidenceNoteMn when it has both;
/// else packTraceNote and packTraceNoteMn when the pack is not scored; else nil.
let confidenceNote: String?
let confidenceNoteMn: String?
/// Show it with every route.
let attribution: String
let note: String
/// Say it to the driver when the pack has no trace scores: confidenceNote, en and mn; nil when scored.
let traceNote: String?
let traceNoteMn: String?
/// The body as JSON bytes, keys sorted.
func bodyJSON() throws -> Data
}
/// What packRoute(_:stops:day:closures:) throws, with ClosuresError.
enum PackRouteError: CustomStringConvertible, Equatable, Error, Sendable {
case noCosting
case noBbox
/// A route needs 2 stops or more.
case fewStops(Int)
/// A stop that is not a finite lon, lat.
case badStop(Int)
case outside(stop: Int, point: LonLat, pack: String)
/// A stop inside a closure ring: Valhalla has no road there. Refuse the route, as GET /v1/route does (422
/// end_in_closure).
case endInClosure(stop: Int, closure: String)
var description: String { get }
}
/// What to say when a pack has no trace scores (confidence osm_only), in English.
let packTraceNote: String
/// The same in Mongolian.
let packTraceNoteMn: String
/// Offline: the Valhalla request for a route through `stops` (2 or more) on the pack: the manifest's costing and
/// costing_options, the route day's closure rings as exclude_polygons (from `closures`, a newer GET /v1/closures
/// answer, else the pack's block), units km. Throws PackRouteError for a manifest with no costing or bbox, under 2
/// stops, a stop outside the pack's bbox or inside an avoided ring; ClosuresError for the day.
func packRoute(_ manifest: PackRouteManifest, stops: [LonLat], day: String = ubToday(), closures: ClosuresResponse? = nil) throws -> PackRoutePasses.swift
swift
/// A pass's fields, in PassFeature.properties.
struct PassProperties: Codable, Equatable, Sendable {
/// mountain_pass when OSM has that tag, else saddle.
let kind: String
let name: String?
/// The OSM name as written, when it mixed Latin and Cyrillic in a word and name is folded to one script. nil when
/// name is the OSM text. Show name. Packs before offline v12 lack it.
let nameOsm: String?
let nameEn: String?
/// The OSM ele tag read as metres. nil when OSM has none, or only other text, as "7000 ft": see eleOsm.
let eleM: Double?
/// The OSM ele tag as written.
let eleOsm: String?
/// The OSM node id.
let nodeId: Int64
/// The Copernicus GLO-30 DEM height of the cell the node falls in, whole metres: a second source beside eleM,
/// never mixed into it. nil when the pack had no DEM tile there; packs built before 2026-10-03 lack it.
let demM: Double?
/// True when eleM and demM are both there and more than dem.differM (50 m) apart, false within, nil when either
/// is missing. True says one of the two is wrong, not which. Packs built before passes v3 lack it.
let heightsDiffer: Bool?
/// The OSM car ways through the node. Empty on a new track alone.
let routeWayIds: [Int64]
let newTrack: Bool
/// The ways' OSM highway and surface tags, as on crossings. nil on a new track alone.
let road: CrossingRoad?
}
/// One pass in an offline pack's passes.geojson: an OSM mountain_pass=yes or natural=saddle node of a car way.
struct PassFeature: Codable, Equatable, Sendable {
let type: String
let geometry: CrossingGeometry
let properties: PassProperties
}
/// The pack's DEM block: where demM comes from. Show attribution wherever a DEM height shows.
struct PassDem: Codable, Equatable, Sendable {
let source: String
let attribution: String
let rule: String
let ruleMn: String
let note: String
let noteMn: String
/// DEM tiles read.
let tiles: Int
/// Tiles the build had no copy of: passes there have demM nil.
let missing: [String]
/// Heights further apart than this, m, set heightsDiffer. Packs before passes v3 lack it and the three below.
let differM: Double?
let differRule: String?
let differRuleMn: String?
/// Passes with heightsDiffer true, all Mongolia.
let differ: Int?
}
/// An offline pack's passes.geojson (manifest files row and passes block; index.json passes_sha256). Check its
/// sha256 against the manifest before use. Packs built before 2026-10-03 have none.
struct PackPasses: Codable, Equatable, Sendable {
let type: String
/// Passes in the file, all Mongolia.
let written: Int
/// Per kind, all Mongolia.
let counts: [String : Int]
let named: Int
/// Names in the file folded to one script, all Mongolia, and the rule, en and mn. nil in packs before offline v12.
let namesFolded: Int?
let nameRule: String?
let nameRuleMn: String?
/// Passes with a height in metres.
let withEle: Int
/// Passes with a DEM height. nil in packs built before 2026-10-03.
let withDem: Int?
/// nil in packs built before 2026-10-03.
let dem: PassDem?
/// A route goes over a pass when its line comes this close, m.
let matchM: Double
let rule: String
let ruleMn: String
let source: String
let note: String
let noteMn: String
let features: [PassFeature]
/// The file's bytes, as in the pack.
init(json: Data) throws
}
/// A pass the route goes over.
struct PassOnRoute: Equatable, Sendable {
/// mountain_pass or saddle.
let kind: String
let point: LonLat
let name: String?
/// The OSM text when name was folded to one script, else nil. Show name.
let nameOsm: String?
let nameEn: String?
let eleM: Double?
let eleOsm: String?
let nodeId: Int64
/// The DEM height, whole metres, beside eleM. nil when the pack has none for this pass. Label it DEM.
let demM: Double?
/// The pack's flag: true when eleM and demM disagree by more than dem.differM. nil when either is missing or the
/// pack has no flag. Show both heights and the dem differRule when true.
let heightsDiffer: Bool?
let newTrack: Bool
let road: CrossingRoad?
/// Along the route to its point nearest the pass, m, rounded. A tie goes to the earlier pass.
let alongM: Double
/// From the route line, m, rounded to 0.1.
let offM: Double
}
/// What passesOnRoute(_:line:) returns.
struct RoutePasses: Equatable, Sendable {
let matchM: Double
/// In route order.
let passes: [PassOnRoute]
/// The highest eleM of these passes, m. nil when none has a height: not "flat", OSM has no number.
let topM: Double?
/// The highest demM of these passes, m. nil when none has one. Not mixed with topM.
let topDemM: Double?
/// How many of these passes have heightsDiffer true. nil when the pack has no flag (no dem.differRule): not
/// checked, not 0.
let differ: Int?
/// The pack's DEM block, nil when the pack has none. Show its attribution with a DEM height.
let dem: PassDem?
/// Show with the passes: from OSM tags, not field checked.
let note: String
let noteMn: String
let rule: String
let ruleMn: String
/// How the pack folds a name that mixes Latin and Cyrillic, en and mn. nil when the pack has no rule.
let nameRule: String?
let nameRuleMn: String?
}
/// What passesOnRoute(_:line:) throws.
enum PassesError: CustomStringConvertible, Equatable, Error, Sendable {
/// A route line needs at least 2 points.
case shortLine(Int)
var description: String { get }
}
/// Offline: the OSM mountain passes a route line goes over, from an offline pack's passes.geojson, in route order. A
/// route goes over a pass when its line comes within the pack's matchM (5 m) of the pass node, as lane D's route
/// pages. Throws PassesError for a line under 2 points.
func passesOnRoute(_ passes: PackPasses, line: [LonLat]) throws -> RoutePassesPlaces.swift
swift
/// Default number of places kept. The least picked, then the longest unpicked, go first.
let placesMax: Int
/// Key in the partner's store. A new format gets a new key. Same key and format as the JS SDK.
let placesKey: String
/// Where kept places live across app launches: UserDefaultsPlaceStore, the Keychain, a test map.
protocol PlaceStore : Sendable {
/// The value kept under key, nil when none. A thrown error is ignored: the cache starts empty.
func string(forKey key: String) throws -> String?
/// Keeps value under key, replacing the old one. A thrown error is ignored: memory still answers.
func set(_ value: String, forKey key: String) throws
/// Drops the value under key. Called by forgetPlaces().
func remove(forKey key: String) throws
}
/// UserDefaults as a PlaceStore. Pass UserDefaults(suiteName:) to keep the places apart from the app's settings.
struct UserDefaultsPlaceStore: PlaceStore, Sendable {
let defaults: UserDefaults
init(_ defaults: UserDefaults = .standard)
func string(forKey key: String) -> String?
func set(_ value: String, forKey key: String)
func remove(forKey key: String)
}
/// Client(placeCache:): where picked places are kept, and how many.
struct PlaceCacheOptions: Sendable {
/// 1 to 1000. Default 100.
var max: Int
/// Keeps the places across app launches. Default nil: memory only, gone with the client.
var store: PlaceStore?
init(max: Int = placesMax, store: PlaceStore? = nil)
}
/// A place the user picked: the fields of a geocode result without score, layer and near, which belong to one
/// answer, not to the place.
struct Place: Codable, Equatable, Sendable {
let officialAddress: OfficialAddress?
let officialStatus: String
let unofficial: Bool
let officialSource: String?
let officialDate: String?
let code: String?
let kind: String
/// Stable id. Never show it to people as an address.
let id: String
let nameMn: String?
let nameEn: String?
let longMn: String?
let longEn: String?
let point: LonLat
let confidence: Int?
let source: String
var sourceDate: String?
var floor: Int?
var flat: String?
var claimed: Bool?
var buildingType: String?
init(_ r: GeocodeResult)
}Pois.swift
swift
/// A place's fields, in PoiFeature.properties.
struct PoiProperties: Codable, Equatable, Sendable {
/// fuel or ger_camp.
let kind: String
/// The OSM element, N or W and the id, as N123.
let osm: String
/// Clean name from the state registry match.
let name: String
let nameEn: String?
/// State registration number.
let regNumber: String
}
/// One registered place in an offline pack's pois.geojson. Unregistered places are never in the file.
struct PoiFeature: Codable, Equatable, Sendable {
let type: String
let geometry: CrossingGeometry
let properties: PoiProperties
}
/// Places of one kind, all Mongolia: matched to an official registration, and not.
struct PoiKindCount: Codable, Equatable, Sendable {
let registered: Int
let unregistered: Int
}
/// Per kind, all Mongolia.
struct PoiCounts: Codable, Equatable, Sendable {
let fuel: PoiKindCount?
let gerCamp: PoiKindCount?
}
/// An offline pack's pois.geojson (files[2]; index.json pois_sha256). Check its sha256 against the manifest before use.
struct PackPois: Codable, Equatable, Sendable {
let type: String
/// false: the registry could not be read when the pack was built, so no place is listed.
let registryChecked: Bool
let counts: PoiCounts
let written: Int
let rule: String
let ruleMn: String
let source: String
let note: String
let noteMn: String
let features: [PoiFeature]
/// The file's bytes, as in the pack.
init(json: Data) throws
}
/// A registered fuel station or ger camp near the route.
struct PoiOnRoute: Equatable, Sendable {
/// fuel or ger_camp.
let kind: String
let point: LonLat
let osm: String
let name: String
let nameEn: String?
let regNumber: String
/// Along the route to its point nearest the place, m, rounded. A tie goes to the earlier pass.
let alongM: Double
/// From the route line, m, rounded.
let offM: Double
}
/// What poisOnRoute(_:line:nearM:) returns.
struct RoutePois: Equatable, Sendable {
let nearM: Double
/// Registered places only, in route order.
let pois: [PoiOnRoute]
/// false: no place was listed because the registry was not read; say so, do not say "none".
let registryChecked: Bool
/// Unregistered fuel stations in the pack, all Mongolia, not near this route: the pack has no place for them. An
/// empty pois is not "no fuel on the route" while this is above 0.
let unlistedFuel: Int
/// Unregistered ger camps in the pack, all Mongolia, as unlistedFuel.
let unlistedGerCamp: Int
/// Show with the places: from OSM, not field checked; unregistered places are counted, not shown.
let note: String
let noteMn: String
}
/// What poisOnRoute(_:line:nearM:) throws.
enum PoisError: CustomStringConvertible, Equatable, Error, Sendable {
/// A route line needs at least 2 points.
case shortLine(Int)
/// Not above 0.
case badNearM(Double)
var description: String { get }
}
/// lane D's route pages: fuel and ger camps within 2 km of the line.
let poiNearM: Double
/// Offline: the registered fuel stations and ger camps within `nearM` (default 2000) of a route line, from an offline
/// pack's pois.geojson, in route order. Throws PoisError for a line under 2 points or a nearM not above 0.
func poisOnRoute(_ pois: PackPois, line: [LonLat], nearM: Double = poiNearM) throws -> RoutePoisQr.swift
swift
/// A QR as rows of modules: `modules[y][x]` is true for a dark module. `size` modules a side (21 to 177), no quiet
/// zone: leave 4 light modules around it when drawing. `link` is the text it holds.
struct DoorQr: Equatable, Sendable {
let link: String
let version: Int
let size: Int
let modules: [[Bool]]
}
/// The QR of a door: the modules of doorLink(text, unit:). nil when the text cannot be a code. A link longer than
/// level M holds (2,331 bytes, a unit of about 2,300 characters) is also nil.
func doorQr(_ text: String, unit: String? = nil) -> DoorQr?
/// The QR of a door as an SVG document, black on white, for a web view, a share sheet or print. nil as doorQr. Each
/// module is `px` wide; `margin` light modules around it (4, the standard's minimum quiet zone). The SVG is
/// (size + 2 * margin) * px a side. Throws DockError `invalid_option` for px not above 0 or a margin under 0.
func doorQrSvg(_ text: String, unit: String? = nil, px: Double = 4, margin: Int = 4) throws -> String?
/// The QR of a door as a grey CGImage, black on white, `px` pixels a module and `margin` light modules around it:
/// `UIImage(cgImage:)`, SwiftUI `Image(decorative:scale:)`, or print. nil as doorQr. Throws DockError
/// `invalid_option` for px under 1 or a margin under 0.
func doorQrImage(_ text: String, unit: String? = nil, px: Int = 8, margin: Int = 4) throws -> CGImage?Sand.swift
swift
/// A GeoJSON LineString: the stretch of the way inside the sand area.
struct SandGeometry: Codable, Equatable, Sendable {
let type: String
let coordinates: [LonLat]
}
/// A stretch's fields, in SandFeature.properties.
struct SandProperties: Codable, Equatable, Sendable {
/// The area's OSM element, as way/123 or relation/123.
let area: String
/// The area's OSM name.
let name: String?
/// The OSM name as written, when it mixed Latin and Cyrillic in a word and name is folded to one script. nil when
/// name is the OSM text. Show name. Packs before offline v11 lack it.
let nameOsm: String?
/// The stretch's length, km.
let km: Double
/// The car way's OSM id. nil on a new track alone.
let wayId: Int64?
let newTrack: Bool
/// The way's OSM highway and surface tags, as on crossings. nil on a new track alone.
let road: CrossingRoad?
}
/// One stretch in an offline pack's sand.geojson: the part of one car way inside an OSM natural=sand area.
struct SandFeature: Codable, Equatable, Sendable {
let type: String
let geometry: SandGeometry
let properties: SandProperties
}
/// An offline pack's sand.geojson (manifest files row and sand block; index.json sand_sha256). Check its sha256
/// against the manifest before use. Packs built before 2026-10-03 have none.
struct PackSand: Codable, Equatable, Sendable {
let type: String
/// Stretches in the file, all Mongolia.
let written: Int
let km: Double
/// OSM sand areas the stretches lie in.
let areas: Int
/// Stretches in a named area.
let named: Int
/// Names in the file folded to one script, all Mongolia, and the rule, en and mn. nil in packs before offline v11.
let namesFolded: Int?
let nameRule: String?
let nameRuleMn: String?
/// Stretches on a paved road (road.paved true), as town streets drawn inside sand.
let onPaved: Int
/// A route runs on a stretch where its line comes this close, m.
let matchM: Double
let rule: String
let ruleMn: String
let source: String
let note: String
let noteMn: String
let features: [SandFeature]
/// The file's bytes, as in the pack.
init(json: Data) throws
}
/// A stretch through OSM sand the route runs on.
struct SandOnRoute: Equatable, Sendable {
let area: String
let name: String?
/// The OSM text when name was folded to one script, else nil. Show name.
let nameOsm: String?
/// The whole stretch, km, from the pack. The route may run on part of it: onM.
let km: Double
let wayId: Int64?
let newTrack: Bool
let road: CrossingRoad?
/// Along the route to where it meets the stretch, m, rounded.
let alongM: Double
/// Metres of the stretch the route runs on, rounded.
let onM: Double
/// The stretch's first point the route meets, in route order.
let point: LonLat
}
/// What sandOnRoute(_:line:) returns.
struct RouteSand: Equatable, Sendable {
let matchM: Double
let minOnM: Double
/// In route order.
let stretches: [SandOnRoute]
/// Sum of onM, m.
let onM: Double
/// Show with the stretches: from OSM tags, not field checked.
let note: String
let noteMn: String
let rule: String
let ruleMn: String
/// How the pack folds a name that mixes Latin and Cyrillic, en and mn. nil when the pack has no rule.
let nameRule: String?
let nameRuleMn: String?
}
/// What sandOnRoute(_:line:) throws.
enum SandError: CustomStringConvertible, Equatable, Error, Sendable {
/// A route line needs at least 2 points.
case shortLine(Int)
var description: String { get }
}
/// A route that runs on less of a stretch than this, m, only crosses it, unless it runs on all of the stretch.
let sandMinOnM: Double
/// Offline: the stretches through OSM sand a route line runs on, from an offline pack's sand.geojson, in route order.
/// The same rule as wetlandsOnRoute: the stretch is cut in pieces of at most matchM; a piece is on the route when both
/// its ends lie within matchM of the line. A stretch is on the route when its pieces on the route make at least
/// sandMinOnM, or when all of it is on the route. Throws SandError for a line under 2 points.
func sandOnRoute(_ sand: PackSand, line: [LonLat]) throws -> RouteSandStyle.swift
swift
/// A JSON value, for styles. Equal when the JSON is equal; numbers compare as Double.
enum JSONValue: Codable, Equatable, ExpressibleByArrayLiteral, ExpressibleByBooleanLiteral, ExpressibleByDictionaryLiteral, ExpressibleByExtendedGraphemeClusterLiteral, ExpressibleByFloatLiteral, ExpressibleByIntegerLiteral, ExpressibleByStringLiteral, ExpressibleByUnicodeScalarLiteral, Sendable {
case string(String)
case number(Double)
case bool(Bool)
case array([JSONValue])
case object([String : JSONValue])
case null
init(stringLiteral v: String)
init(integerLiteral v: Int)
init(floatLiteral v: Double)
init(booleanLiteral v: Bool)
init(arrayLiteral v: JSONValue...)
init(dictionaryLiteral v: (String, JSONValue)...)
init(from decoder: Decoder) throws
func encode(to encoder: Encoder) throws
/// A member of an object, nil otherwise.
subscript(key: String) -> JSONValue? { get }
/// The JSON text, keys sorted. The string MapLibre Native reads from a style file.
func jsonString() -> String
}
/// Ulaanbaatar, Sükhbaatar Square.
let ubCenter: LonLat
/// A saved style id: "st_" and 10 characters of the key alphabet.
func isValidStyleId(_ id: String) -> Bool
/// Colors and extrusion for dockStyle(_:options:) and dockLayers(_:). nil fields keep the defaults.
struct StyleOptions: Equatable, Sendable {
/// Background color. Default a light paper tone.
var background: String?
/// Building fill (or extrusion) color. Default a warm grey.
var building: String?
/// Building outline color.
var buildingOutline: String?
/// Extrude buildings by height_m (or levels x 3 m). Default false: flat 2D.
var extrude: Bool
init(background: String? = nil, building: String? = nil, buildingOutline: String? = nil, extrude: Bool = false)
}
/// Sources named dock-building and dock-entrance, TileJSON from the API, without the key.
func dockSources(_ baseURL: URL) -> [String : JSONValue]
/// Building fill and outline, entrance dots by confidence. Add on top of any basemap style. Entrance colors are fixed:
/// confidence reads the same on every map (PLAN.md 5).
func dockLayers(_ options: StyleOptions = StyleOptions()) -> [JSONValue]
/// A whole style: background, dock buildings, dock entrances. Source URLs without the key: see Client.styleJSON.
func dockStyle(_ baseURL: URL, options: StyleOptions = StyleOptions()) -> JSONValue
/// An offline pack's manifest block `basemap` (nil in packs built before 2026-10-03, or with no base map).
struct PackBasemap: Codable, Equatable, Sendable {
var method: String
var file: String
var format: String
var schema: String
var schemaVersion: String
var tileType: String
var tiles: Int
var minzoom: Int
var maxzoom: Int
var bounds: [Double]
var layers: [String]
var excludedLayers: [String]
var languages: [String]
var osmTime: String?
/// Show on the map: the source carries it, so MapLibre's attribution shows it.
var attribution: String
var rule: String
var ruleMn: String
/// The block from the pack's manifest.json bytes; nil when the pack has no base map.
static func fromManifest(_ json: Data) throws -> PackBasemap?
}
/// Label language of the base map: names as name:mn and name:en.
enum BasemapLang: Equatable, Hashable, RawRepresentable, Sendable {
case mn
case en
}
/// What basemapStyle(_:url:options:) takes.
struct BasemapStyleOptions: Equatable, Sendable {
/// Label language, one of the block's languages. A name missing in it falls back to OSM's name.
var lang: BasemapLang
/// A glyphs URL ({fontstack}, {range}). The pack carries no fonts: without glyphs the style has no labels.
var glyphs: String?
/// Font stack on that glyphs URL. Default Noto Sans Regular.
var fonts: [String]?
/// Background color. Default the dock style's paper tone.
var background: String?
init(lang: BasemapLang = .mn, glyphs: String? = nil, fonts: [String]? = nil, background: String? = nil)
}
/// Layers the base map must not carry: business names (shown only when registered) and OSM house numbers.
let basemapExcluded: [String]
/// What basemapStyle(_:url:options:) throws.
enum StyleError: CustomStringConvertible, Equatable, Error, Sendable {
/// The pack's manifest has no basemap block.
case noBasemap
/// The block is not OpenMapTiles vector PMTiles: format, tile type, schema.
case notOpenMapTiles(String, String, String)
/// The block carries layers from basemapExcluded.
case excludedLayers([String])
/// The block has no names in this language; its languages.
case noLang(String, [String])
/// Empty basemap.pmtiles URL.
case emptyURL
/// Not "st_" and 10 characters of the key alphabet.
case badStyleId(String)
var description: String { get }
}
/// A whole style for an offline pack's base map: land, water, tracks and roads, boundaries, buildings, and with
/// glyphs also place, water and road names. url is where the app keeps basemap.pmtiles, a file:// URL; the source
/// asks for it as pmtiles://, which MapLibre Native reads itself. Throws StyleError for no block, a block that is not
/// the pack's base map or carries a poi or housenumber layer, a lang the block lacks, or an empty url.
func basemapStyle(_ basemap: PackBasemap?, url: String, options: BasemapStyleOptions = BasemapStyleOptions()) throws -> JSONValueSuggest.swift
swift
/// PLAN 18: "suggestions from the third character".
let suggestMinChars: Int
/// Wait after the last key before asking, ms. Under the 250 ms people notice, over most gaps between keys.
let suggestDelayMs: Int
/// A door read from a typed code, or a geocode result.
enum Suggestion: Equatable, Sendable {
case door(Door)
case result(GeocodeResult)
}
/// What to show a person for a suggestion. Anything without a matched official address ends in "(албан бус)" /
/// "(unofficial)".
func label(_ item: Suggestion, lang: Lang = .mn) -> String
/// Text in, suggestions out. `input(_:)` on every change of the field; `show` gets the list for the text as it
/// stands, never an older one. Under minChars the list is emptied at once and nothing is sent. A text that reads as
/// a building code (parseDoorCode) is looked up as a door first; a code with no door falls through to the words. A
/// pasted door link (parseDoorLink) is looked up as a door only. An
/// empty list for a text of minChars or more means no match.
@MainActor final class Suggester: Sendable {
/// - limit: geocode results per list, 1 to 20. Default 5. A door from a typed code comes on top of them.
/// - proximity: asked on each request, the person or the map centre. Nearer places first.
/// - types: only these kinds, as geocode types: a street picker passes [.street]. nil or empty:
/// every kind. A typed code or a pasted door link is looked up as a door only when types has .door.
/// - show: the list and the text it is for, on the main actor.
/// - fail: a DockError or another failure of the request, on the main actor.
@MainActor init(client: Client, limit: Int = 5, proximity: (@MainActor () -> LonLat?)? = nil, types: [GeocodeType]? = nil, minChars: Int = suggestMinChars, delayMs: Int = suggestDelayMs, show: @escaping @MainActor ([Suggestion], String) -> Void, fail: @escaping @MainActor (Error) -> Void)
/// The field now reads text. From minChars characters on, asks delayMs after the last call; under them, empties the list.
@MainActor func input(_ text: String)
/// Stops the wait and the request in flight. Their answers are dropped.
@MainActor func cancel()
/// The person chose this suggestion. Stops what is in flight; a geocode result goes to client.pick (offline
/// places, opted-in telemetry), a door from a code does not. Show label(item) in the field.
@MainActor func choose(_ item: Suggestion)
}Telemetry.swift
swift
/// API limits (api/src/modules/telemetry/telemetry-input.ts).
let telemetryBatch: Int
/// Characters of typed text kept per search, counted as the API counts them (code points). The rest is cut.
let telemetryMaxChars: Int
/// Results kept per search.
let telemetryMaxResults: Int
/// What the user picked: kind and id as geocode gave them, rank 1 = the first result shown.
struct SearchPick: Encodable, Equatable, Sendable {
let kind: String
let id: String
let rank: Int
}
/// One search as the API takes it. Text, count and pick only: no time, point, device or session.
struct SearchEvent: Encodable, Equatable, Sendable {
let q: String
let results: Int
let picked: SearchPick?
}Trace.swift
swift
/// API limits (api/src/modules/traces/trace-input.ts).
let traceFormat: String
/// Points per upload. stopTrace() splits a longer trip.
let traceMaxPoints: Int
/// Mongolia with a margin: west, south, east, north. A point outside would refuse the whole upload.
let mnBBox: (west: Double, south: Double, east: Double, north: Double)
/// Fixes worse than this, in meters, are left out. Accuracy itself is never sent.
let traceMaxAccuracyM: Double
/// The user's yes. The only value: there is no way to record or send without it.
enum Consent: Codable, Equatable, Hashable, RawRepresentable, Sendable {
case optIn
}
/// One position from the device. Only lon, lat and time are ever sent.
struct PositionFix: Equatable, Sendable {
let lon: Double
let lat: Double
/// Meters, nil when not known (kept).
let accuracy: Double?
let timestamp: Date
init(lon: Double, lat: Double, accuracy: Double? = nil, timestamp: Date)
/// From Core Location. A negative horizontalAccuracy means no fix: it is passed on and left out.
init(_ location: CLLocation)
}
/// Where fixes come from: a CLLocationManager delegate in the app, or a test. The SDK never asks for location
/// permission itself; the app does, and its own Info.plist text says why.
protocol PositionSource : AnyObject, Sendable {
/// Call `onFix` for each new position until stop().
func start(_ onFix: @escaping @Sendable (PositionFix) -> Void)
/// Stop calling onFix. The client calls it when the trip stops or is cancelled, and when it goes away.
func stop()
}
/// A PositionSource the app pushes fixes into, from its CLLocationManagerDelegate:
/// `for l in locations { feed.push(PositionFix(l)) }`. A fix pushed while no trip is recorded is dropped.
final class PositionFeed: PositionSource, Sendable {
/// A feed with no trip yet. Pass it to startTrace(consent:source:maxAccuracyM:).
init()
/// Called by the client when a trip starts: fixes pushed from now on go to `onFix`.
func start(_ onFix: @escaping @Sendable (PositionFix) -> Void)
/// Drops the callback: later fixes are dropped.
func stop()
/// Hands a fix to the trip being recorded. Dropped when none is.
func push(_ fix: PositionFix)
}
/// [lon, lat, t]: degrees WGS84 and whole seconds UTC. Nothing else per point.
struct TracePoint: Codable, Equatable, Sendable {
let lon: Double
let lat: Double
let t: Int64
init(lon: Double, lat: Double, t: Int64)
init(from decoder: Decoder) throws
func encode(to encoder: Encoder) throws
}Types.swift
swift
/// A WGS84 point. On the wire it is [lon, lat], longitude first.
struct LonLat: Codable, Equatable, Hashable, Sendable {
var lon: Double
var lat: Double
init(_ lon: Double, _ lat: Double)
init(from decoder: Decoder) throws
func encode(to encoder: Encoder) throws
}
/// National format, as written by the source.
struct OfficialAddress: Codable, Equatable, Sendable {
let country: String
let cityOrAimag: String
let districtOrSoum: String
let khorooOrBag: String?
let streetOrMicrodistrict: String?
let buildingOrKhashaa: String?
let entrance: String?
let floor: String?
let unit: String?
/// Unified postal code from the state register, "13381-0017".
let postalCode: String?
/// The building's own name from the state register, when it has one.
let buildingName: String?
}
/// The entrance a building code points to.
struct Entrance: Codable, Equatable, Sendable {
/// door, gate, vehicle_gate or stairwell.
let kind: String
/// Entrance or gate number as people say it.
let letter: String?
let floorsServed: [Int]?
}
/// A flat, office or shop behind a door, when the code was given with a unit.
struct Unit: Codable, Equatable, Sendable {
let number: String
let floor: Int?
/// flat, office, shop, stall or kiosk.
let kind: String
}
/// A door. Official address first, code after it. No owner, no phone.
struct Door: Codable, Equatable, Sendable {
/// Confirmed driver taps for this door since its point last moved. 0 when none. nil from an API before this field.
var confirmations: Int?
let officialAddress: OfficialAddress?
/// matched, partial or none.
let officialStatus: String
/// true unless officialStatus is matched. Show "unofficial" when true.
let unofficial: Bool
let officialSource: String?
let officialDate: String?
let code: String
let naturalMn: String?
let naturalEn: String?
let longMn: String?
let longEn: String?
let point: LonLat
let entrance: Entrance?
let unit: Unit?
/// PLAN 5 level, 0 to 4. nil means unknown.
let confidence: Int?
let source: String
let instructionsMn: String?
let instructionsEn: String?
let aliases: [String]
/// The date of the door or unit row behind the code, YYYY-MM-DD. nil: not known. Absent before API 0.87.0.
var sourceDate: String?
}
/// One geocode answer. kind: door, business, building, district, khoroo, area, street or landmark.
struct GeocodeResult: Codable, Equatable, Sendable {
/// The official address as one Cyrillic line, postal code last. nil when none is matched.
var officialLine: String?
/// A building with an indoor map: venue_id, levels (floor numbers, lowest first) and the units the query names. nil for every other row.
var indoor: JSONValue?
let officialAddress: OfficialAddress?
let officialStatus: String
let unofficial: Bool
let officialSource: String?
let officialDate: String?
/// Building code. null when the place has none.
let code: String?
let kind: String
/// Stable id. Never show it to people as an address.
let id: String
let nameMn: String?
let nameEn: String?
let longMn: String?
let longEn: String?
let point: LonLat
let confidence: Int?
let source: String
/// Higher is better. Compare only with results of the same layer in one response.
let score: Double
/// 1: the words of a name or address matched. 2: the place description matched the meaning; after every layer 1, except near rows. 3: near rows reordered by a reranking model (API 0.30.0).
let layer: Int
/// The landmark a landmark-relative query named ("Хүннү моллын ард"), for a place found around it. nil otherwise.
let near: GeocodeNear?
/// A bus stop: the city bus lines that call at it ("Ч:41"). nil for every other place.
let lines: [String]?
/// A business or landmark: its map category, the one nearby gives ("pharmacy"). nil for any other place and when unknown.
let category: String?
/// The date of the row's current version, YYYY-MM-DD, or the register's date for a door. nil: not known. Absent before API 0.87.0.
var sourceDate: String?
/// A company from a building's directory (API 0.90.0): its floor from the legal address in the state register. nil when not said, and for every other place.
var floor: Int?
/// A company from a building's directory (API 0.90.0): its flat or office number (N тоот). nil when not said.
var flat: String?
/// A business: true when its company has a claim the state register confirmed, false when not or pending (API 0.95). nil for any other kind.
var claimed: Bool?
/// A building: apartment, ger_house, commercial, public, industrial, garage or other. nil when the building has no type yet, and for any other kind.
var buildingType: String?
/// A business, landmark or street: the khoroo number its point stands in. nil when no polygon covers it, and for any other kind.
var khoroo: Int?
/// A business: true when its point lies inside a restricted site, so a client hides the claim link and any edit. nil for any other kind.
var restricted: Bool?
/// A building: true when its whole name is only a kind word (Үсчин, Дэлгүүр), so a client shows it as a kind. nil when not checked, and for any other kind.
var nameIsKindWord: Bool?
/// A building: the OSM category of the one POI in its footprint ("shop=hairdresser"). nil when unknown, and for any other kind.
var poiCategory: String?
/// A building: up to 5 company names registered at it. Empty when none; nil for any other kind.
var poiNames: [String]?
}
/// The landmark, building or door a near-me query was read against.
struct GeocodeNear: Codable, Equatable, Sendable {
/// landmark, building or door.
let kind: String
let id: String
let nameMn: String?
let nameEn: String?
/// north, east, south or west (within 55 degrees), near or beside (the whole circle).
let relation: String
/// From the landmark to the place, 150 at most.
let metres: Double
}
/// GET /v1/geocode, or places picked on this device when offline is true.
struct GeocodeResponse: Codable, Equatable, Sendable {
/// Units inside a building with an indoor map that the query names (up to 5), each with venue_id, level, name_mn and point. nil when none is named.
var indoorUnits: [JSONValue]?
let results: [GeocodeResult]
/// Set when the whole query is a unit code, alone ("7QSVX") or spoken ("7QSVX, 12 давхар, 1204 тоот"). nil
/// otherwise and offline.
let unit: GeocodeUnit?
/// true only when the answer came from this device's picked places, not the API. Not on the wire.
var offline: Bool
}
/// A unit code found in the query: the unit card as GET /v1/door/{code} answers it, plus the floor and flat said
/// after the code.
struct GeocodeUnit: Codable, Equatable, Sendable {
let officialAddress: OfficialAddress?
let officialStatus: String
/// true unless officialStatus is matched. Show "unofficial" when true.
let unofficial: Bool
let officialSource: String?
let officialDate: String?
let code: String
/// building or khashaa.
let kind: String
/// The official address as one Cyrillic line, postal code last. nil when nothing is known.
let officialLine: String?
let nameMn: String?
let nameEn: String?
/// A point inside the footprint.
let point: LonLat
/// N in "N давхар"; nil when not said.
let floor: Int?
/// N in "N тоот"; nil when not said.
let flat: String?
/// Where the unit row came from. nil when unknown.
let source: String?
/// How sure dock is of the building row, 0 to 4; lower for a state-only building. nil: unknown.
let confidence: Double?
/// The date of the door or unit row behind the code, YYYY-MM-DD. nil: not known. Absent before API 0.87.0.
var sourceDate: String?
/// The building holds an indoor map: its venue id (venue(_:)). nil when it holds none.
var venueId: String?
/// District and khoroo the building lies in, only when its address is not matched. Never the official address. nil when matched or not known.
var areaLine: String?
}
/// One reverse result.
struct ReverseResult: Codable, Equatable, Sendable {
/// The official address as one Cyrillic line, postal code last. nil when none is matched.
var officialLine: String?
/// A building with an indoor map: venue_id, levels (floor numbers, lowest first) and the units the query names. nil for every other row.
var indoor: JSONValue?
let officialAddress: OfficialAddress?
let officialStatus: String
let unofficial: Bool
let officialSource: String?
let officialDate: String?
let code: String?
let kind: String
let id: String
let nameMn: String?
let nameEn: String?
let longMn: String?
let longEn: String?
let point: LonLat
let confidence: Int?
let source: String
/// Metres from the query point. 0 means the point is inside.
let distanceM: Double
/// A bus stop: the city bus lines that call at it ("Ч:41"). nil for every other place.
let lines: [String]?
/// A business or landmark: its map category, the one nearby gives ("pharmacy"). nil for any other place and when unknown.
let category: String?
/// The date of the row's current version, YYYY-MM-DD, or the register's date for a door. nil: not known. Absent before API 0.87.0.
var sourceDate: String?
/// A business: true when its company has a claim the state register confirmed, false when not or pending (API 0.95). nil for any other kind.
var claimed: Bool?
/// A building: apartment, ger_house, commercial, public, industrial, garage or other. nil when the building has no type yet, and for any other kind.
var buildingType: String?
/// A business, landmark or street: the khoroo number its point stands in. nil when no polygon covers it, and for any other kind.
var khoroo: Int?
/// A business: true when its point lies inside a restricted site, so a client hides the claim link and any edit. nil for any other kind.
var restricted: Bool?
/// A building: true when its whole name is only a kind word (Үсчин, Дэлгүүр), so a client shows it as a kind. nil when not checked, and for any other kind.
var nameIsKindWord: Bool?
/// A building: the OSM category of the one POI in its footprint ("shop=hairdresser"). nil when unknown, and for any other kind.
var poiCategory: String?
/// A building: up to 5 company names registered at it. Empty when none; nil for any other kind.
var poiNames: [String]?
}
/// A kind geocode can keep (types), as the API's PLACE_KINDS.
enum GeocodeType: CaseIterable, Codable, Equatable, Hashable, RawRepresentable, Sendable {
case door
case business
case building
case district
case khoroo
case area
case street
case landmark
}
/// A kind reverse can keep (types), as the API's REVERSE_KINDS: district and khoroo always come with the answer.
enum ReverseType: CaseIterable, Codable, Equatable, Hashable, RawRepresentable, Sendable {
case door
case business
case building
case landmark
}
/// GET /v1/reverse.
struct ReverseResponse: Codable, Equatable, Sendable {
let point: LonLat
let districtMn: String?
let districtEn: String?
/// nil when no khoroo polygon covers the point. Never guessed.
let khoroo: Int?
/// The soum and aimag covering the point (OSM boundaries, API 0.104.0). nil when no polygon covers it.
var soumMn: String?
var aimagMn: String?
let results: [ReverseResult]
/// true when the point itself lies inside a restricted site: results is then empty, and a client hides the claim link and any edit.
var restricted: Bool
}
/// A category nearby takes: the map's place icons, as the API's NEARBY_CATEGORIES. atm, bank, cafe, car_wash, fuel, hotel, pharmacy,
/// restaurant and shop are registered businesses only, so they answer nothing until a business matches the registry:
/// a business through its door, or a store of a registered chain (code nil).
enum NearbyCategory: CaseIterable, Codable, Equatable, Hashable, RawRepresentable, Sendable {
case atm
case bank
case bridge
case cafe
case car_wash
case culture
case embassy
case fuel
case government
case hospital
case hotel
case kindergarten
case mall
case market
case monument
case office
case park
case pharmacy
case religion
case restaurant
case school
case shop
case sport
case station
case stop
case university
}
/// One nearby result.
struct NearbyResult: Codable, Equatable, Sendable {
/// The official address as one Cyrillic line, postal code last. nil when none is matched.
var officialLine: String?
/// A building with an indoor map: venue_id, levels (floor numbers, lowest first) and the units the query names. nil for every other row.
var indoor: JSONValue?
let officialAddress: OfficialAddress?
let officialStatus: String
let unofficial: Bool
let officialSource: String?
let officialDate: String?
/// Unit code of the place: a door, a business through its door, or the building or хашаа a store or company
/// stands in. nil when none is minted yet: show "код алга" and the official address, or none.
let code: String?
let kind: String
let id: String
let nameMn: String?
let nameEn: String?
let longMn: String?
let longEn: String?
let point: LonLat
let confidence: Int?
let source: String
/// The map category, as the place icon. String, so a new category from the API never fails a decode.
let category: String
/// The OpenStreetMap opening_hours tag as written; may be old. nil when the source has none.
let openingHours: String?
/// Where openingHours came from. nil when openingHours is nil.
let hoursSource: String?
/// Open now in Ulaanbaatar time, from a plain opening_hours tag. nil when unknown: no tag, or not a plain one.
let openNow: Bool?
/// When the place closes today, HH:MM in Ulaanbaatar time, while openNow is true. nil when closed, unknown, or open 24/7.
let openUntil: String?
/// Only when nearby was asked for photo: one openly licensed photo of a landmark or building. nil when none or not asked.
var photo: PlacePhoto?
/// Metres from the query point.
let distanceM: Double
/// A bus stop: the city bus lines that call at it ("Ч:41"). nil when the capital's public transport data lists none.
let lines: [String]?
/// The date of the row's current version, YYYY-MM-DD, or the register's date for a door. nil: not known. Absent before API 0.87.0.
var sourceDate: String?
/// A registered company from a building's directory: its floor from the state register. nil when not said, and for every other place. Absent before API 0.92.1.
var floor: Int?
/// A company's flat or office number (N тоот). nil when not said. Absent before API 0.92.1.
var flat: String?
/// A business: true when its company has a claim the state register confirmed, false when not or pending (API 0.95). nil for any other kind.
var claimed: Bool?
/// A business, landmark or street: the khoroo number its point stands in. nil when no polygon covers it, and for any other kind.
var khoroo: Int?
/// A business: true when its point lies inside a restricted site, so a client hides the claim link and any edit. nil for any other kind.
var restricted: Bool?
}
/// GET /v1/nearby.
struct NearbyResponse: Codable, Equatable, Sendable {
let point: LonLat
/// Nearest first, within radius. Empty when none.
let results: [NearbyResult]
/// How many more places of these categories lie within radius past limit. 0 when results holds them all.
let more: Int
/// Only with open=1: how many of the nearest 20 places have no readable hours (openNow nil). They are not in results.
var hoursUnknown: Int?
}
/// Second-source check of a building footprint. confidence is nil when the run gave none: unknown.
struct FootprintCheck: Codable, Equatable, Sendable {
/// confirmed, new or doubtful.
let verdict: String
let source: String
let confidence: Double?
let checkedAt: String
}
/// One openly licensed photo of a place. Show credit and license beside it.
struct PlacePhoto: Codable, Equatable, Sendable {
let url: String
let credit: String
/// CC BY, CC BY-SA, CC0 or public domain.
let license: String
let source: String
}
/// Where to point the map from above when a place has no photo.
struct MapFromAbove: Codable, Equatable, Sendable {
let lon: Double
let lat: Double
let zoom: Int
}
/// Ids of what a door stands in. Ids only, never shown to people as an address. nil when not known.
struct Parents: Codable, Equatable, Sendable {
/// The door of a business. nil for a door.
let door: String?
let building: String?
/// Khashaa (plot).
let plot: String?
let area: String?
let street: String?
/// nil when no khoroo polygon covers the door. Never guessed.
let khoroo: String?
let district: String?
}
/// GET /v1/address/{id}: one place by the id geocode, reverse or changes gave.
struct Address: Codable, Equatable, Sendable {
/// The official address as one Cyrillic line, postal code last. nil when none is matched.
var officialLine: String?
/// A building with an indoor map: venue_id, levels (floor numbers, lowest first) and the units the query names. nil for every other row.
var indoor: JSONValue?
let officialAddress: OfficialAddress?
let officialStatus: String
let unofficial: Bool
let officialSource: String?
let officialDate: String?
let code: String?
let kind: String
let id: String
let nameMn: String?
let nameEn: String?
let longMn: String?
let longEn: String?
let point: LonLat
let confidence: Int?
let source: String
/// Doors and businesses; a khoroo carries its district only; nil for every other kind.
let parents: Parents?
/// A bus stop: the city bus lines that call at it ("Ч:41"). nil for every other place.
let lines: [String]?
/// A business or landmark: its map category, the one nearby gives ("pharmacy"). nil for any other place and when unknown.
let category: String?
/// The date of the row's current version, YYYY-MM-DD, or the register's date for a door. nil: not known. Absent before API 0.87.0.
var sourceDate: String?
/// A company from a building's directory (API 0.90.0): its floor from the legal address in the state register. nil when not said, and for every other place.
var floor: Int?
/// A company from a building's directory (API 0.90.0): its flat or office number (N тоот). nil when not said.
var flat: String?
/// A business: true when its company has a claim the state register confirmed, false when not or pending (API 0.95). nil for any other kind.
var claimed: Bool?
/// A district, khoroo or area (next API patch): its boundary as a GeoJSON Polygon or MultiPolygon, about 5 m simplified. nil for every other kind and where no polygon is held.
var outline: JSONValue?
/// A district, khoroo or area: current buildings and doors inside its boundary, nothing inside a restricted site. nil for every other kind and where the register has no polygon: unknown. 0 is a real zero.
var counts: JSONValue?
/// A business, landmark or street: the khoroo number its point stands in. nil when no polygon covers it, and for any other kind.
var khoroo: Int?
/// A business: true when its point lies inside a restricted site, so a client hides the claim link and any edit. nil for any other kind.
var restricted: Bool?
/// A building: whether its footprint is backed by a second source. nil for other kinds and for a building not yet checked.
var footprintCheck: FootprintCheck?
/// A landmark, business or street: the district its point stands in, in Mongolian. nil when no polygon covers it, and for any other kind.
var districtMn: String?
/// A landmark or building: one openly licensed photo within 30 m. nil when there is none.
var photo: PlacePhoto?
/// Set only when photo is nil: where to point the map from above (zoom 19 for a building, door or business, 17 otherwise). nil when there is a photo or the site is restricted.
var mapFromAbove: MapFromAbove?
}
/// One place changed, in changes(since:limit:cursor:).
struct Change: Codable, Equatable, Sendable {
/// The id place(_:) takes.
let id: String
let kind: String
/// current: fetch it again with place(_:). retired: drop it, the id is never reused. hidden: drop it, it may come back.
let state: String
/// Last change, UTC, microseconds.
let changedAt: String
}
/// GET /v1/changes. Window [since, until).
struct ChangesResponse: Codable, Equatable, Sendable {
let since: String
/// The last index refresh. When next is nil, poll again with since = until.
let until: String
/// Oldest first. One row per place, its last change.
let changes: [Change]
/// More in this window: pass as cursor. nil: window done.
let next: String?
}
/// How the route is travelled.
enum RouteMode: Codable, Equatable, Hashable, RawRepresentable, Sendable {
case driving
case walking
case cycling
}
/// The door at one end of a route. Show "(unofficial)" when unofficial is true.
struct RouteDoor: Codable, Equatable, Sendable {
let officialAddress: OfficialAddress?
let officialStatus: String
let unofficial: Bool
let code: String
let naturalMn: String?
let naturalEn: String?
let entrance: Entrance?
let confidence: Int?
}
/// The entrance at one end of a route, when that end was sent as an entrance id. Show "(unofficial)" when
/// unofficial is true; confidence 0 with source generated was placed by rule (таамаг).
struct RouteEntrance: Codable, Equatable, Sendable {
let id: String
let building: String
/// nil: no door minted for this entrance yet.
let code: String?
let officialAddress: OfficialAddress?
let officialStatus: String
let unofficial: Bool
/// door, gate, vehicle_gate or stairwell.
let kind: String
let letter: String?
let confidence: Int?
let source: String
}
/// One end of a route.
struct RouteEnd: Codable, Equatable, Sendable {
/// What was asked for: the entrance when a code was given.
let point: LonLat
/// Where the line starts or ends, on the road network.
let snapped: LonLat
/// Straight metres from snapped to point. Walked, never drawn as road.
let gapM: Double
let door: RouteDoor?
/// The entrance, when this end was sent as an entrance id. Absent from older APIs.
let entrance: RouteEntrance?
/// The address unit this end was sent as, by its code; nil for any other end.
let unit: RouteUnit?
/// The date of the row's current version, YYYY-MM-DD, or the register's date for a door. nil: not known. Absent before API 0.87.0.
var sourceDate: String?
}
/// The address unit (building or khashaa) a route end was given as, by its code. The route ends at its street side.
struct RouteUnit: Codable, Equatable, Sendable {
let code: String
/// building or khashaa.
let kind: String
let officialAddress: OfficialAddress?
let officialStatus: String
/// true unless officialStatus is matched. Show "unofficial" when true.
let unofficial: Bool
/// true: the end is the gate, or the outline of the building or khashaa at the street, within about 25 m of where the line meets the street. false: the outline is farther than that from the street, the walk is longer.
let streetSide: Bool
}
/// A GeoJSON LineString: type "LineString" and [lon, lat] points.
struct LineString: Codable, Equatable, Sendable {
let type: String
let coordinates: [LonLat]
}
/// GET /v1/route. No live traffic yet.
/// The road closures a route avoided (GET /v1/closures, active on asOf).
struct RouteClosures: Codable, Equatable, Sendable {
/// The route day, YYYY-MM-DD, Ulaanbaatar.
let asOf: String
/// Closure ids, in id order. Each was kept out of the route, whether or not it came near. Show them with it.
let avoided: [String]
}
/// Driving time with all partners' measured moving speed per road (API 0.48.0).
struct RouteMeasured: Codable, Equatable, Sendable {
/// YYYY-MM: the latest month GET /v1/traces/roads publishes.
let month: String
/// The hour band of departAt whose speeds were read (API 0.50.0), a RoadBand raw value: "am_peak", "pm_peak",
/// "off_peak". nil without departAt (all hours) or from an API before 0.50.0.
let band: String?
/// Meters of the line on roads with a published speed that month. 0: none, and durationS is the free-flow one.
let roadsM: Double
/// Seconds with those roads at their measured moving speed, the rest at the router's. A month average of the band.
let durationS: Double
}
/// GET /v1/route. durationS is free-flow; measured has partners' speeds. Avoids the road closures active today.
struct Route: Codable, Equatable, Sendable {
let mode: String
let distanceM: Double
/// Seconds at the router's free-flow speeds.
let durationS: Double
/// Driving only; nil when walking or cycling, when speeds could not be read, or from an API before 0.48.0.
let measured: RouteMeasured?
/// Driving: seconds with a typical load by road class, hour and weekday; nil when walking, cycling or unreadable (API 0.97.19).
var expectedDurationS: Int?
/// Where that load comes from: model (a table), probes (partners' phones, not yet).
var trafficSource: String?
/// The label to show beside expectedDurationS.
var trafficNote: String?
let geometry: LineString
/// One per hop, in order: from to via[0], ..., the last to to; one without via. nil from an API before 0.67.0.
let legs: [TripLeg]?
let from: RouteEnd
/// The via ends in the order sent, snapped where the line passes them; empty without. nil before API 0.67.0.
let via: [RouteEnd]?
let to: RouteEnd
let closures: RouteClosures
let source: String
}
/// GET /v1/matrix (API 0.63.0): free-flow travel time and distance from every from to every to in one call. Cell
/// [i][j] goes from from[i] to to[j]; nil where no path joins them. No measured speeds, no line.
struct Matrix: Codable, Equatable, Sendable {
let mode: String
/// Seconds at the router's free-flow speeds, as durationS in a route.
let durationsS: [[Double?]]
/// Meters from from[i].snapped to to[j].snapped; nil where durationsS is nil.
let distancesM: [[Double?]]
/// The sources in the order asked, each as a route end.
let from: [RouteEnd]
/// The targets in the order asked, each as a route end.
let to: [RouteEnd]
let closures: RouteClosures
let source: String
}
/// GET /v1/isochrone (API 0.64.0): GeoJSON, one feature per contour, the largest first, so drawn in order each
/// smaller one lies on top. Free-flow speeds, closures avoided. mode, from, closures and source sit beside the features.
struct Isochrone: Codable, Equatable, Sendable {
/// "FeatureCollection".
let type: String
let features: [IsochroneFeature]
let mode: String
/// Where the areas are reached from, as a route end.
let from: RouteEnd
let closures: RouteClosures
let source: String
}
/// One isochrone contour: the area reached within `properties.contour` minutes.
struct IsochroneFeature: Codable, Equatable, Sendable {
/// "Feature".
let type: String
let properties: IsochroneProperties
let geometry: IsochroneGeometry
}
/// An isochrone contour's fields, in IsochroneFeature.properties.
struct IsochroneProperties: Codable, Equatable, Sendable {
/// Minutes: the area reached from from within this time.
let contour: Int
/// Always "time": minutes, as Mapbox's contours_minutes.
let metric: String
}
/// An isochrone's area: a Polygon, or a MultiPolygon where the area is in pieces. Every ring closed, [lon, lat].
enum IsochroneGeometry: Codable, Equatable, Sendable {
case polygon([[LonLat]])
case multiPolygon([[[LonLat]]])
/// Every piece of the area, each as its rings (outer first, then holes), one for a Polygon: fill them all the same.
var polygons: [[[LonLat]]] { get }
init(from decoder: Decoder) throws
func encode(to encoder: Encoder) throws
}
/// GET /v1/optimized-trips (API 0.66.0): the stops in the order with the least time on the road. trips holds one
/// trip, as Mapbox's answer does; waypoints are the stops in the order sent. Today's closures avoided.
struct OptimizedTrip: Codable, Equatable, Sendable {
let mode: String
/// true: the trip goes back to the first stop. false: it ends at the last stop sent.
let roundtrip: Bool
let trips: [Trip]
let waypoints: [TripWaypoint]
let closures: RouteClosures
let source: String
}
/// The whole trip in the order driven, snapped stop to snapped stop.
struct Trip: Codable, Equatable, Sendable {
let distanceM: Double
/// Seconds on the road at the router's free-flow speeds. No live traffic, no measured speeds, no time at the stops.
let durationS: Double
let geometry: LineString
/// legs[k] goes from the stop with waypointIndex k to the one with k + 1; on a round trip the last goes back to
/// the first.
let legs: [TripLeg]
}
/// One hop of an optimized trip, from one stop to the next in the order driven, or of a route with via (API 0.67.0).
struct TripLeg: Codable, Equatable, Sendable {
/// Meters from one stop to the next along the road network.
let distanceM: Double
/// Seconds from one stop to the next at the router's free-flow speeds.
let durationS: Double
}
/// One stop as sent, a route end with its place in the trip.
struct TripWaypoint: Codable, Equatable, Sendable {
/// What was asked for: the entrance when a code was given.
let point: LonLat
/// Where the line starts or ends, on the road network.
let snapped: LonLat
/// Straight metres from snapped to point. Walked, never drawn as road.
let gapM: Double
let door: RouteDoor?
let entrance: RouteEntrance?
/// The address unit this stop was sent as, by its code; nil for any other stop.
let unit: RouteUnit?
/// Where this stop comes in the trip: 0 is the first, always the first sent.
let waypointIndex: Int
/// The date of the door, unit or entrance behind this stop, YYYY-MM-DD; nil for a bare point. Absent before API 0.87.0.
var sourceDate: String?
}
/// A tile source tilequery(_:sources:radius:limit:geometry:) reads: the building and entrance layers of the map.
enum TilequerySource: CaseIterable, Codable, Equatable, Hashable, RawRepresentable, Sendable {
case building
case entrance
case place
}
/// A feature's geometry type in its tile, as Mapbox's tilequery.geometry; keeps one type in a tilequery.
enum TilequeryGeometry: CaseIterable, Codable, Equatable, Hashable, RawRepresentable, Sendable {
case polygon
case linestring
case point
}
/// GET /v1/tiles/{sources}/tilequery/{lon},{lat} (API 0.68.0), as Mapbox's Tilequery API: GeoJSON, nearest first,
/// then by layer and id. The same rows as the tiles: current, not demolished, nothing in a restricted site.
struct Tilequery: Codable, Equatable, Sendable {
/// "FeatureCollection".
let type: String
let features: [TilequeryFeature]
}
/// One building or entrance at or near the point: a Point, the part of it nearest the point sent.
struct TilequeryFeature: Codable, Equatable, Sendable {
/// "Feature".
let type: String
let geometry: TilequeryPoint
let properties: TilequeryProperties
}
/// A tilequery feature's place: the point sent when it is inside. The 7th decimal is a mark for your organization.
struct TilequeryPoint: Codable, Equatable, Sendable {
/// "Point".
let type: String
let coordinates: LonLat
}
/// The fields of the feature's tile layer, and nothing more: a building has building fields, an entrance entrance
/// fields. nil where the map does not know. No building codes.
struct TilequeryProperties: Codable, Equatable, Sendable {
/// The building or entrance id, as in its tile. Never an address.
let id: String
/// Building only.
let nameMn: String?
/// Building only.
let nameEn: String?
/// Building only: apartment, ger_house, commercial, public, industrial, garage or other.
let type: String?
/// Building only: planned, under_construction or built.
let status: String?
/// Building only. Metres.
let heightM: Double?
/// Building only: where heightM came from. osm:height a tag; levels levels x 3.1 m; default:* a type default;
/// estimated:* footprint shape and size; unknown none.
let heightSource: String?
/// Building only: 3 a tag or editor, 2 levels, 1 type default, 0 estimated. 0 and 1 are estimates, never
/// measurements. nil: no height.
let heightConfidence: Int?
/// Building only.
let levels: Int?
/// Building only: official building number from the state register. nil: no matched or partial official form.
let buildingNumber: String?
/// Building only: the building's name when it is a name, not a purpose. nil: no name or no official form.
let buildingName: String?
/// Entrance only: door, gate, vehicle_gate or stairwell.
let kind: String?
/// Entrance only.
let letter: String?
/// Entrance only: its building. nil: none on record.
let buildingId: String?
/// 0 to 5 (PLAN.md 5). nil: not rated yet.
let confidence: Int?
let source: String
/// Place only: the map category (bank, pharmacy, stop, religion, etc.).
let cat: String?
/// Place only: the map rank (higher shows over lower in collisions).
let rank: Double?
let tilequery: TilequeryInfo
/// A building: whether its footprint is backed by a second source. nil for other kinds and for a building not yet checked.
var footprintCheck: FootprintCheck?
}
/// How a tilequery feature lies from the point sent.
struct TilequeryInfo: Codable, Equatable, Sendable {
/// Metres from the point sent to the nearest part of the feature, to 0.1 m. 0: the point is inside it.
let distance: Double
/// polygon, linestring or point.
let geometry: String
/// The tile source and layer the feature is in: building, entrance or place.
let layer: String
}
/// GET /v1/matching (API 0.65.0): a GPS trace on the road network. One matching per unbroken piece; one tracepoint
/// per point sent, in its order, nil where no road was found for it or it is inside a restricted site.
struct Match: Codable, Equatable, Sendable {
let mode: String
let matchings: [Matching]
let tracepoints: [MatchTracepoint?]
let source: String
}
/// One unbroken piece of a matched trace: the roads it went along, in its order.
struct Matching: Codable, Equatable, Sendable {
let distanceM: Double
/// Seconds at the router's free-flow speed on each road, no turn costs; not the time the trace took.
let durationS: Double
let geometry: LineString
}
/// Where one point sent lies on the matched line.
struct MatchTracepoint: Codable, Equatable, Sendable {
/// The matching this point lies on, an index into matchings.
let matchingsIndex: Int
/// The point on the matched line.
let location: LonLat
/// Straight-line meters from the point sent to location.
let gapM: Double
}
/// POST /v1/door/report. A person reviews it; door data does not change until then.
enum DoorReport: Encodable, Equatable, Sendable {
case wrongLocation(code: String, point: LonLat, note: String? = nil)
case missing(code: String, note: String? = nil)
case duplicate(code: String, duplicateOf: String, note: String? = nil)
case unmapped(point: LonLat, note: String? = nil)
func encode(to encoder: Encoder) throws
}
/// POST /v1/door-reports.
struct DoorReportReceipt: Codable, Equatable, Sendable {
let id: String
/// queued or already_queued.
let status: String
let kind: String
let code: String?
/// door, building, plot, or nil.
let target: String?
let movedM: Double?
let receivedAt: String
let next: String
}
/// POST /v1/confirm body. A driver on site says a door is there, elsewhere or gone.
struct Confirmation: Encodable, Equatable, Sendable {
/// The door by code, or by the entrance id in the entrance tile layer for entrances with no code yet.
enum Target: Equatable, Sendable {
case code(String)
case entrance(String)
}
/// confirmed and wrongLocation carry the point the driver tapped on the map: the placed point.
enum Result: Equatable, Sendable {
case confirmed(tap: LonLat)
case wrongLocation(tap: LonLat)
case missing
}
var target: Target
var result: Result
/// Phone GPS on site. A check only, never the placed point: within 40 m of the tap.
var device: LonLat
/// Your own opaque id for the driver (A-Z a-z 0-9 . _ : -, up to 64). Never a phone number, e-mail or name.
var driver: String?
var note: String?
/// When the driver was on site, for a confirmation queued offline. At most 7 days ago.
var observedAt: Date?
init(_ target: Target, _ result: Result, device: LonLat, driver: String? = nil, note: String? = nil, observedAt: Date? = nil)
func encode(to encoder: Encoder) throws
}
/// POST /v1/confirm. Map data does not change at once.
struct ConfirmReceipt: Codable, Equatable, Sendable {
/// Same id for a repeat.
let id: String
/// recorded, or already_recorded: the same driver (or your org, with no driver) said the same in the last 24 h.
let status: String
let result: String
/// door, entrance or unit (the code named a building or khashaa: an arrival).
let target: String
let code: String?
/// The entrance confirmed, also for a door code. nil for a unit code.
let entrance: String?
/// Metres from the tap to the entrance on the map. nil for missing.
let movedM: Double?
/// Metres from the tap (missing: the entrance) to the phone GPS.
let gpsM: Double
let observedAt: String?
let receivedAt: String
/// confidence: counts toward the entrance confidence (PLAN.md 5). review: a person checks it first. arrival: recorded as an arrival at a building or khashaa, no entrance raised.
let next: String
}
/// Confirmations and door reports by result. duplicate and unmapped come from door reports.
struct ConfirmCounts: Codable, Equatable, Sendable {
let confirmed: Int
let wrongLocation: Int
let missing: Int
let duplicate: Int
/// A real door with no code yet.
let unmapped: Int
}
/// One Ulaanbaatar day the drivers were on site (observed_at, else received). The counts as in ConfirmCounts.
struct ConfirmDay: Codable, Equatable, Sendable {
/// YYYY-MM-DD.
let day: String
/// Different drivers that day, by your driver ids. Rows with no driver id are not counted here.
let drivers: Int
let confirmed: Int
let wrongLocation: Int
let missing: Int
let duplicate: Int
let unmapped: Int
}
/// A failure point: a door or entrance your drivers said is wrong, missing or a duplicate.
struct ConfirmFlagged: Codable, Equatable, Sendable {
/// nil when your drivers named the entrance, not a code.
let code: String?
/// The entrance id, as in the entrance tile layer.
let entrance: String
/// true when the door or entrance has since been retired.
let retired: Bool
let wrongLocation: Int
let missing: Int
let duplicate: Int
/// The newest of them, on site.
let lastAt: String
}
/// GET /v1/confirm/own: your organization's rows only.
struct OwnConfirmations: Codable, Equatable, Sendable {
/// YYYY-MM, Ulaanbaatar.
let month: String
/// false while confirmations queued offline can still join; true from 8 days after the month ends.
let closed: Bool
let totals: ConfirmCounts
/// Different drivers in the month, by your driver ids. Never the ids.
let drivers: Int
/// Days with at least one row, oldest first.
let days: [ConfirmDay]
/// Most first, at most 100. None inside a restricted site.
let flagged: [ConfirmFlagged]
}
/// Daily caps; nil is no cap.
struct UsageCaps: Codable, Equatable, Sendable {
let dailyQuota: Int?
let tileDailyQuota: Int?
let doorMissCap: Int?
}
/// What a free org gets on the partner plan. Prices are not published yet.
struct UsageUpgrade: Codable, Equatable, Sendable {
let plan: String
let caps: UsageCaps
let rateLimit: Int
let tileRateLimit: Int
let addedScopes: [String]
}
/// The key that made the usage call.
struct UsageKey: Codable, Equatable, Sendable {
/// First 11 characters of the key that made this call.
let prefix: String?
let scopes: [String]
let rateLimit: Int
let tileRateLimit: Int
}
/// One day in usage(days:).
struct UsageDay: Codable, Equatable, Sendable {
/// Ulaanbaatar day, YYYY-MM-DD.
let day: String
let calls: Int
let tiles: Int
let doorMisses: Int
let keys: Int
}
/// One route of the org over the days asked (API 0.62.0).
struct UsageEndpoint: Codable, Equatable, Sendable {
/// Method and route pattern, e.g. `GET /v1/door/:code`. Never a code, a name or a query.
let endpoint: String
/// Requests to this route. The tiles route counts tiles.
let calls: Int
/// Of those, lookups that found no door.
let misses: Int
}
/// GET /v1/usage: the calling key's organization. Caps are nil when there is no cap.
struct UsageResponse: Codable, Equatable, Sendable {
let org: String
/// free: made by POST /v1/signup. custom: a partner org.
let plan: String
/// The partner plan for a free org, nil for a partner org.
let upgrade: UsageUpgrade?
let timezone: String
/// Unix seconds of the next daily reset.
let reset: Int
let key: UsageKey
let caps: UsageCaps
/// Features open to the org, A to Z, e.g. `cargo.eta` (API 0.51.0). Routes of any other feature answer 403
/// `feature_off`. nil from an API before 0.51.0.
let features: [String]?
/// Newest first.
let days: [UsageDay]
/// Every route the org called over the same days, most calls first, then A to Z (API 0.62.0). nil from an API
/// before 0.62.0.
let endpoints: [UsageEndpoint]?
}
/// POST /v1/telemetry/search.
struct SearchTelemetryReceipt: Codable, Equatable, Sendable {
let stored: Int
/// Text that was only a phone or an e-mail address, or a pick not in the index.
let dropped: Int
}
/// POST /v1/traces.
struct TraceReceipt: Codable, Equatable, Sendable {
/// Keep it to fetch or delete the trip. nil: nothing was stored (every point was inside a restricted site).
let id: String?
let points: Int
/// Points left out: inside a restricted site.
let restricted: Int
/// Your organization sent this trip before; id is the first upload.
let duplicate: Bool
/// Raw points are erased after this day, YYYY-MM-DD.
let purgeAfter: String?
}
/// A stored trip's line. Each coordinate is [lon, lat, t].
struct TraceLine: Codable, Equatable, Sendable {
let type: String
let coordinates: [[Double]]
}
/// A stored trip's fields, in Trace.properties.
struct TraceProperties: Codable, Equatable, Sendable {
let receivedDay: String
let purgeAfter: String
let points: Int
let restricted: Int
let deletedAt: String?
/// partner or retention, nil while the points are kept.
let deletedReason: String?
}
/// GET /v1/traces/{id}: your trip as stored, GeoJSON. geometry is nil once deleted or past purge_after.
struct Trace: Codable, Equatable, Sendable {
let type: String
let id: String
let geometry: TraceLine?
let properties: TraceProperties
}
/// DELETE /v1/traces/{id}. deleted is true also when the points were gone before.
struct TraceDeleted: Codable, Equatable, Sendable {
let id: String
let deleted: Bool
}
/// west, south, east, north in degrees.
struct BBox: Equatable, Sendable {
var west: Double
var south: Double
var east: Double
var north: Double
init(west: Double, south: Double, east: Double, north: Double)
}
/// A cell's square, GeoJSON Polygon: one closed ring of [lon, lat].
struct TraceCellPolygon: Codable, Equatable, Sendable {
let type: String
let coordinates: [[[Double]]]
}
/// A cell's fields, in TraceCell.properties.
struct TraceCellProperties: Codable, Equatable, Sendable {
/// Distinct trips through the cell that month.
let trips: Int
}
/// One 500 m cell of the fixed grid in a month. id is "x/y", the same cell every month.
struct TraceCell: Codable, Equatable, Sendable {
let type: String
let id: String
let geometry: TraceCellPolygon
let properties: TraceCellProperties
}
/// GET /v1/traces/cells: all partners together, only cells that meet `rule`. No cell means too few, not zero.
struct TraceCells: Codable, Equatable, Sendable {
let type: String
/// YYYY-MM, Ulaanbaatar.
let month: String
/// Keys as the API writes them (min_orgs, cell, period).
let rule: [String : JSONValue]
let features: [TraceCell]
}
/// A cell's fields, in TraceSpeed.properties.
struct TraceSpeedProperties: Codable, Equatable, Sendable {
/// Counted meters over counted seconds of all partners' trips in the cell, to 0.1. No trip count.
let kmH: Double
}
/// One 500 m cell of the trip cells grid with all partners' moving speed that month. id is "x/y", as TraceCell.
struct TraceSpeed: Codable, Equatable, Sendable {
let type: String
let id: String
let geometry: TraceCellPolygon
let properties: TraceSpeedProperties
}
/// GET /v1/traces/speeds: all partners together, only cells that meet `rule`. No cell means too few trips, not slow.
struct TraceSpeeds: Codable, Equatable, Sendable {
let type: String
/// YYYY-MM, Ulaanbaatar.
let month: String
/// The group rule each cell passed, and how a segment and km_h are measured, keys as the API writes them.
let rule: [String : JSONValue]
/// Cells north to south, then west to east.
let features: [TraceSpeed]
}
/// A road's line: dock's current road with that OSM id, a LineString, or a MultiLineString when it is in pieces.
enum TraceRoadGeometry: Codable, Equatable, Sendable {
case lineString([LonLat])
case multiLineString([[LonLat]])
/// Every piece of the line, one for a LineString: draw them all the same way.
var lines: [[LonLat]] { get }
init(from decoder: Decoder) throws
func encode(to encoder: Encoder) throws
}
/// A road's fields, in TraceRoad.properties.
struct TraceRoadProperties: Codable, Equatable, Sendable {
/// Counted meters over counted seconds of all partners' trips matched to the way, to 0.1. No trip count.
let kmH: Double
/// The road's names and OSM highway class, nil when unknown.
let nameMn: String?
let nameEn: String?
let highway: String?
}
/// One OSM way with all partners' moving speed that month. id is the OSM way id as text: it can pass 2^53 one day.
struct TraceRoad: Codable, Equatable, Sendable {
let type: String
let id: String
let geometry: TraceRoadGeometry
let properties: TraceRoadProperties
}
/// Hour band of GET /v1/traces/roads (API 0.49.0), by the Ulaanbaatar time of a trip's first stored point: amPeak Monday
/// to Friday 07:00 to 09:59, pmPeak Monday to Friday 17:00 to 19:59, offPeak every other hour, Saturday and Sunday whole.
enum RoadBand: CaseIterable, Codable, Equatable, Hashable, RawRepresentable, Sendable {
case amPeak
case pmPeak
case offPeak
}
/// GET /v1/traces/roads: all partners together, only roads that meet `rule`. No road means too few trips, not slow.
struct TraceRoads: Codable, Equatable, Sendable {
let type: String
/// YYYY-MM, Ulaanbaatar.
let month: String
/// The group rule each road passed, and how a trip is matched and km_h measured, keys as the API writes them.
let rule: [String : JSONValue]
/// Roads by OSM way id, smallest first.
let features: [TraceRoad]
}
/// GET /v1/traces/cells/own: your organization's trips only, every cell with one of them.
struct OwnTraceCells: Codable, Equatable, Sendable {
let type: String
/// YYYY-MM, Ulaanbaatar.
let month: String
/// false while trips received now still count; true from 14 days after the month ends.
let closed: Bool
let rule: [String : JSONValue]
let features: [TraceCell]
}
/// Trips per whole arrival minute.
struct ArrivalMinute: Codable, Equatable, Sendable {
/// Whole minutes; 60 is 60 or more.
let minutes: Int
let trips: Int
}
/// A cell's fields, in ArrivalCell.properties.
struct ArrivalCellProperties: Codable, Equatable, Sendable {
/// Your trips that ended in the cell that month.
let trips: Int
/// Of them, arrivals of 5 minutes or more.
let slow: Int
/// Median arrival minutes in the cell, nearest rank.
let median: Int
}
/// A 500 m cell of the trip cells grid where your trips ended. id is "x/y", the same cell every month.
struct ArrivalCell: Codable, Equatable, Sendable {
let type: String
let id: String
let geometry: TraceCellPolygon
let properties: ArrivalCellProperties
}
/// GET /v1/traces/arrivals/own: how long your trips spend in the last 200 m. Your organization's trips only.
struct OwnArrivals: Codable, Equatable, Sendable {
let type: String
/// YYYY-MM, Ulaanbaatar.
let month: String
/// false while trips received now still count; true from 14 days after the month ends.
let closed: Bool
/// How arrival minutes are measured, keys as the API writes them (radius_m, max_minutes, slow_minutes, ...).
let rule: [String : JSONValue]
/// Your trips with an arrival that month, every cell.
let trips: Int
/// Of them, arrivals of 5 minutes or more.
let slow: Int
/// Nearest rank. nil with no trips.
let median: Int?
let p75: Int?
let p90: Int?
/// Trips per arrival minute, fewest minutes first; minutes with none left out.
let histogram: [ArrivalMinute]
/// Cells your trips ended in; features lists up to 100 of them.
let cells: Int
/// By slow trips, then trips, most first.
let features: [ArrivalCell]
}
/// Trips that started in one Ulaanbaatar weekday and hour: yours in OwnHours, all partners' in AllHours.
struct HourSlot: Codable, Equatable, Sendable {
/// ISO weekday in Ulaanbaatar, 1 Monday to 7 Sunday.
let weekday: Int
/// Hour in Ulaanbaatar, 0 to 23.
let hour: Int
let trips: Int
}
/// GET /v1/traces/hours/own: when your trips start, by weekday and hour. Your organization's trips only.
struct OwnHours: Codable, Equatable, Sendable {
/// YYYY-MM, Ulaanbaatar.
let month: String
/// false while trips received now still count; true from 14 days after the month ends.
let closed: Bool
/// How the weekday and hour are read, keys as the API writes them.
let rule: [String : JSONValue]
/// Your trips that month, each once, at the weekday and hour of its first stored point.
let trips: Int
/// 7 counts, Monday first.
let byWeekday: [Int]
/// 24 counts, hour 0 first.
let byHour: [Int]
/// Weekday and hour with trips, weekday then hour; slots with none left out.
let slots: [HourSlot]
}
/// GET /v1/traces/hours: when trips start, by weekday and hour, all partners together. A published month only.
struct AllHours: Codable, Equatable, Sendable {
/// YYYY-MM, Ulaanbaatar.
let month: String
/// The group rule each slot passed, and how the weekday and hour are read, keys as the API writes them.
let rule: [String : JSONValue]
/// Weekday and hour that passed the rule, weekday then hour. A slot left out had too few trips, not zero. No total.
let slots: [HourSlot]
}
/// A khoroo's area, GeoJSON MultiPolygon: polygons of closed rings of [lon, lat].
struct KhorooPolygon: Codable, Equatable, Sendable {
let type: String
let coordinates: [[[[Double]]]]
}
/// Trips that ended in one khoroo in one Ulaanbaatar hour, all partners together.
struct KhorooHour: Codable, Equatable, Sendable {
/// Hour in Ulaanbaatar of the trip end, 0 to 23.
let hour: Int
let trips: Int
}
/// A khoroo's fields, in TraceKhoroo.properties.
struct TraceKhorooProperties: Codable, Equatable, Sendable {
let districtMn: String
let districtEn: String?
/// Khoroo number in its district.
let khoroo: Int
/// Hours that passed the rule, from 0. An hour left out had too few trips, not zero. No khoroo total.
let hours: [KhorooHour]
}
/// A current khoroo polygon with the hours of arrival that passed the rule. id is the polygon's, never an address.
struct TraceKhoroo: Codable, Equatable, Sendable {
let type: String
let id: String
let geometry: KhorooPolygon
let properties: TraceKhorooProperties
}
/// GET /v1/traces/khoroos: where and when trips end, per khoroo and hour, all partners together. A published month only.
struct TraceKhoroos: Codable, Equatable, Sendable {
let type: String
/// YYYY-MM, Ulaanbaatar.
let month: String
/// The group rule each khoroo and hour passed, and how they are read, keys as the API writes them.
let rule: [String : JSONValue]
/// Khoroos with at least one hour shown, by district then number.
let features: [TraceKhoroo]
}
/// A khoroo's fields, in OwnKhoroo.properties.
struct OwnKhorooProperties: Codable, Equatable, Sendable {
let districtMn: String
let districtEn: String?
/// Khoroo number in its district.
let khoroo: Int
/// Your trips that ended in this khoroo that month.
let trips: Int
/// Your trips per Ulaanbaatar hour of arrival, from 0. Hours with none left out.
let hours: [KhorooHour]
}
/// A current khoroo polygon with your trips that ended in it. id is the polygon's, never an address.
struct OwnKhoroo: Codable, Equatable, Sendable {
let type: String
let id: String
let geometry: KhorooPolygon
let properties: OwnKhorooProperties
}
/// GET /v1/traces/khoroos/own: where and when your trips end, per khoroo and hour. Your organization only, no group rule.
struct OwnKhoroos: Codable, Equatable, Sendable {
let type: String
/// YYYY-MM, Ulaanbaatar.
let month: String
/// false while trips received now still count; true from 14 days after the month ends.
let closed: Bool
/// How the khoroo and hour are read, keys as the API writes them.
let rule: [String : JSONValue]
/// Your trips that month.
let trips: Int
/// Your trips that month ending in no current khoroo polygon. trips is noKhoroo plus every khoroo's trips.
let noKhoroo: Int
/// Khoroos with at least one of your trips, by district then number.
let features: [OwnKhoroo]
}
/// Your trips that month ending at one kind of building.
struct OwnKind: Codable, Equatable, Sendable {
/// The building type: apartment, ger_house, commercial, public, industrial, garage, other; unknown is a building
/// with no type yet, none no building within 30 m.
let kind: String
let trips: Int
}
/// GET /v1/traces/kinds/own: what kind of building your trips end at, per month. Your organization only, no group rule.
struct OwnKinds: Codable, Equatable, Sendable {
/// YYYY-MM, Ulaanbaatar.
let month: String
/// false while trips received now still count; true from 14 days after the month ends.
let closed: Bool
/// How the building and its kind are read, keys as the API writes them.
let rule: [String : JSONValue]
/// Your trips that month, the sum of every kind's trips.
let trips: Int
/// Kinds with at least one of your trips, most trips first, then by name.
let kinds: [OwnKind]
}
/// One entrance in entrancesNear(): nearest first, each with its building and distance. source generated +
/// confidence 0: show as таамаг. No door minted yet: code nil.
struct NearEntrance: Codable, Equatable, Sendable {
let officialAddress: OfficialAddress?
/// matched, partial or none.
let officialStatus: String
/// true unless officialStatus is matched. Show "unofficial" when true.
let unofficial: Bool
let officialSource: String?
let officialDate: String?
/// nil: no door minted for this entrance yet.
let code: String?
/// Never show as an address.
let id: String
/// door, gate, vehicle_gate or stairwell.
let kind: String
/// Entrance or gate number as people say it.
let letter: String?
let floorsServed: [Int]?
let point: LonLat
/// PLAN 5 level; 0 with source generated: таамаг.
let confidence: Int?
let source: String
/// The building id: pass to place(_:) or call tilequery with the entrance layer.
let building: String
let distanceM: Double
/// The date of this entrance's current version, YYYY-MM-DD. nil: not known. Absent before API 0.87.1.
var sourceDate: String?
}
/// GET /v1/entrances/near.
struct NearEntrances: Codable, Equatable, Sendable {
let point: LonLat
/// Nearest first, within radius. Empty when no entrance is that close.
let results: [NearEntrance]
}
/// One organization in a building's directory. Only organizations matched to an official registration are listed.
struct DirectoryEntry: Codable, Equatable, Sendable {
let name: String
/// Floor (давхар). nil when the register does not say.
let floor: Int?
/// Unit (тоот). nil when unknown.
let unit: String?
let category: String?
let source: String
let confidence: Double?
/// Date this version of the entry was recorded.
let sourceDate: String
}
/// GET /v1/address/{id}/directory: "Энд байгаа байгууллагууд" for an office building or mall card.
struct BuildingDirectory: Codable, Equatable, Sendable {
/// The building id, as sent or the one the code names. nil for a хашаа code.
let building: String?
/// The building's code. nil until one is minted.
let code: String?
/// By floor (unknown floor last), then unit, then name. Empty when none is known.
let entries: [DirectoryEntry]
}Venue.swift
swift
/// One floor of a venue. `ordinal` is the floor as people say it: 0 ground, 1 first, -1 basement.
struct IndoorLevel: Codable, Equatable, Sendable {
let ordinal: Int
let shortNameMn: String
let nameMn: String?
let outdoor: Bool
let source: String
let confidence: Double?
}
/// Where a venue stands: the district and khoroo covering it, and soum and aimag from the OSM admin polygons.
struct VenueAdmin: Codable, Equatable, Sendable {
let districtMn: String?
let districtEn: String?
let khoroo: Int?
let soumMn: String?
let aimagMn: String?
}
/// GET /v1/venue/{id}: a building with an indoor map, its outline (GeoJSON Polygon) and its current floors, lowest first.
struct Venue: Codable, Equatable, Sendable {
let id: String
let nameMn: String
let nameEn: String?
let category: String
let source: String
let confidence: Double?
/// The building code of the real-map building the venue stands in; nil until it has one.
let buildingCode: String?
let admin: VenueAdmin?
let outline: JSONValue
let levels: [IndoorLevel]
}
/// One unit, opening or amenity on a floor. `properties["feature_type"]` says which; then category, level, source,
/// confidence, and the names, number and area a unit has.
struct LevelFeature: Codable, Equatable, Sendable {
let type: String
let id: String
let geometry: JSONValue
let properties: JSONValue
}
/// GET /v1/venue/{id}/level/{n}: one floor as GeoJSON.
struct VenueLevel: Codable, Equatable, Sendable {
let type: String
let venueId: String
let level: Int
let features: [LevelFeature]
}
/// GET /v1/venue/{id}/spot: what a printed plate for one unit says. `link` is what the plate's QR holds.
struct VenueSpot: Codable, Equatable, Sendable {
let venueId: String
let venueNameMn: String
let unitId: String
let level: Int
let levelNameMn: String
let nameMn: String?
let number: String?
let label: String
let point: LonLat
let link: String
let source: String
let confidence: Double?
}
/// One step of a walk inside a venue, in Mongolian, with the floor it is on. `at` is where the step begins.
struct IndoorStep: Codable, Equatable, Sendable {
let floor: Int
let text: String
let distanceM: Double
let at: LonLat
}
/// One floor of a walk: its line and how it ends: stairs, escalator, elevator or arrive. `toFloor` is the floor a
/// connector reaches, nil on arrival.
struct IndoorLeg: Codable, Equatable, Sendable {
let floor: Int
let distanceM: Double
let geometry: LineString
let endsWith: String
let toFloor: Int?
}
/// GET /v1/venue/{id}/route: the walk inside a venue to one unit, floor by floor. `to` is the unit: level, point,
/// name_mn, number, source, confidence.
struct VenueRoute: Codable, Equatable, Sendable {
let venueId: String
let distanceM: Double
let durationS: Double
let legs: [IndoorLeg]
let steps: [IndoorStep]
let to: JSONValue
}
/// The street entrance a road route ends at.
struct VenueEntrance: Codable, Equatable, Sendable {
let level: Int
let point: LonLat
let coreEntranceId: String?
}
/// One road step, in both languages.
struct VenueRoadStep: Codable, Equatable, Sendable {
let mn: String
let en: String
let distanceM: Double
let at: LonLat
}
/// The road part of venue directions: the line to the street entrance.
struct VenueRoad: Codable, Equatable, Sendable {
let mode: String
let distanceM: Double
let durationS: Double
let geometry: LineString
let steps: [VenueRoadStep]
let entrance: VenueEntrance
}
/// GET /v1/venue/{id}/directions: the road to the street entrance, then the walk inside. Distance and duration are
/// road plus walk.
struct VenueDirections: Codable, Equatable, Sendable {
let venueId: String
let distanceM: Double
let durationS: Double
let road: VenueRoad
let indoor: VenueRoute
}Water.swift
swift
/// A water point's fields, in WaterFeature.properties.
struct WaterProperties: Codable, Equatable, Sendable {
/// The first of drinking_water, water_point, water_tap, water_well, spring the OSM element carries.
let kind: String
let name: String?
/// The OSM name as written, when it mixed Latin and Cyrillic in a word and name is folded to one script. nil when
/// name is the OSM text. Show name. Packs before offline v12 lack it.
let nameOsm: String?
let nameEn: String?
/// Only what OSM says: true for drinking_water=yes (or amenity=drinking_water with no such tag), false for
/// drinking_water=no, nil when OSM says nothing. Never guessed from kind.
let drinkable: Bool?
/// The OSM drinking_water tag as written.
let drinkingWater: String?
/// The OSM pump tag as written.
let pump: String?
/// The OSM element, as node/1 or way/1.
let osm: String
}
/// One water point in an offline pack's water.geojson: an OSM node or way, a way at a point on its surface.
struct WaterFeature: Codable, Equatable, Sendable {
let type: String
let geometry: CrossingGeometry
let properties: WaterProperties
}
/// Water points per drinkable value.
struct WaterDrinkable: Codable, Equatable, Sendable {
let yes: Int
let no: Int
/// OSM says nothing.
let unknown: Int
}
/// An offline pack's water.geojson (manifest files row and water block; index.json water_sha256). Check its sha256
/// against the manifest before use. Packs built before 2026-10-03 have none.
struct PackWater: Codable, Equatable, Sendable {
let type: String
/// Water points in the file, all Mongolia.
let written: Int
/// Per kind, all Mongolia.
let counts: [String : Int]
let named: Int
/// Names in the file folded to one script, all Mongolia, and the rule, en and mn. nil in packs before offline v12.
let namesFolded: Int?
let nameRule: String?
let nameRuleMn: String?
/// All Mongolia.
let drinkable: WaterDrinkable
/// A water point is near a route within this many metres of its line, as fuel and ger camps.
let nearM: Double
let rule: String
let ruleMn: String
let nearRule: String
let nearRuleMn: String
let source: String
let note: String
let noteMn: String
let features: [WaterFeature]
/// The file's bytes, as in the pack.
init(json: Data) throws
}
/// A water point near the route.
struct WaterOnRoute: Equatable, Sendable {
let kind: String
let point: LonLat
let name: String?
/// The OSM text when name was folded to one script, else nil. Show name.
let nameOsm: String?
let nameEn: String?
let drinkable: Bool?
let drinkingWater: String?
let pump: String?
let osm: String
/// Along the route to its point nearest the water, m, rounded. A tie goes to the earlier pass.
let alongM: Double
/// From the route line, m, rounded.
let offM: Double
}
/// What waterOnRoute(_:line:nearM:) returns.
struct RouteWater: Equatable, Sendable {
let nearM: Double
/// In route order.
let water: [WaterOnRoute]
/// Of these points. unknown: OSM says nothing, not "not drinkable".
let drinkable: WaterDrinkable
/// Show with the points: from OSM tags, not field checked; a well may be dry, broken or locked.
let note: String
let noteMn: String
let rule: String
let ruleMn: String
let nearRule: String
let nearRuleMn: String
/// How the pack folds a name that mixes Latin and Cyrillic, en and mn. nil when the pack has no rule.
let nameRule: String?
let nameRuleMn: String?
}
/// What waterOnRoute(_:line:nearM:) throws.
enum WaterError: CustomStringConvertible, Equatable, Error, Sendable {
/// A route line needs at least 2 points.
case shortLine(Int)
/// Not above 0.
case badNearM(Double)
var description: String { get }
}
/// Offline: the OSM water points (wells, springs, taps, drinking water) within `nearM` of a route line, from an
/// offline pack's water.geojson, in route order. nearM nil is the pack's nearM (2000), lane D's route pages. Throws
/// WaterError for a line under 2 points or a nearM not above 0.
func waterOnRoute(_ water: PackWater, line: [LonLat], nearM: Double? = nil) throws -> RouteWaterWetlands.swift
swift
/// A GeoJSON LineString: the stretch of the way inside the wetland area.
struct WetlandGeometry: Codable, Equatable, Sendable {
let type: String
let coordinates: [LonLat]
}
/// A stretch's fields, in WetlandFeature.properties.
struct WetlandProperties: Codable, Equatable, Sendable {
/// The area's OSM wetland tag, as marsh, bog, wet_meadow or fen; unknown when the area has none.
let wetland: String
/// The area's OSM element, as way/123 or relation/123.
let area: String
/// The area's OSM name.
let name: String?
/// The OSM name as written, when it mixed Latin and Cyrillic in a word and name is folded to one script. nil when
/// name is the OSM text. Show name. Packs before offline v12 lack it.
let nameOsm: String?
/// The stretch's length, km.
let km: Double
/// The car way's OSM id. nil on a new track alone.
let wayId: Int64?
let newTrack: Bool
/// The way's OSM highway and surface tags, as on crossings. nil on a new track alone.
let road: CrossingRoad?
}
/// One stretch in an offline pack's wetlands.geojson: the part of one car way inside an OSM natural=wetland area.
struct WetlandFeature: Codable, Equatable, Sendable {
let type: String
let geometry: WetlandGeometry
let properties: WetlandProperties
}
/// Stretches of one wetland kind, all Mongolia, and their length in km.
struct WetlandCount: Codable, Equatable, Sendable {
let stretches: Int
let km: Double
}
/// An offline pack's wetlands.geojson (manifest files row and wetlands block; index.json wetlands_sha256). Check its
/// sha256 against the manifest before use. Packs built before 2026-10-03 have none.
struct PackWetlands: Codable, Equatable, Sendable {
let type: String
/// Stretches in the file, all Mongolia.
let written: Int
let km: Double
/// OSM wetland areas the stretches lie in.
let areas: Int
/// Names in the file folded to one script, all Mongolia, and the rule, en and mn. nil in packs before offline v12.
let namesFolded: Int?
let nameRule: String?
let nameRuleMn: String?
/// Per wetland kind, all Mongolia.
let counts: [String : WetlandCount]
/// A route runs on a stretch where its line comes this close, m.
let matchM: Double
let rule: String
let ruleMn: String
let source: String
let note: String
let noteMn: String
let features: [WetlandFeature]
/// The file's bytes, as in the pack.
init(json: Data) throws
}
/// A stretch through OSM wetland the route runs on.
struct WetlandOnRoute: Equatable, Sendable {
let wetland: String
let area: String
let name: String?
/// The OSM text when name was folded to one script, else nil. Show name.
let nameOsm: String?
/// The whole stretch, km, from the pack. The route may run on part of it: onM.
let km: Double
let wayId: Int64?
let newTrack: Bool
let road: CrossingRoad?
/// Along the route to where it meets the stretch, m, rounded.
let alongM: Double
/// Metres of the stretch the route runs on, rounded.
let onM: Double
/// The stretch's first point the route meets, in route order.
let point: LonLat
}
/// What wetlandsOnRoute(_:line:) returns.
struct RouteWetlands: Equatable, Sendable {
let matchM: Double
let minOnM: Double
/// In route order.
let stretches: [WetlandOnRoute]
/// Sum of onM, m.
let onM: Double
/// Show with the stretches: from OSM tags, not field checked.
let note: String
let noteMn: String
let rule: String
let ruleMn: String
/// How the pack folds a name that mixes Latin and Cyrillic, en and mn. nil when the pack has no rule.
let nameRule: String?
let nameRuleMn: String?
}
/// What wetlandsOnRoute(_:line:) throws.
enum WetlandsError: CustomStringConvertible, Equatable, Error, Sendable {
/// A route line needs at least 2 points.
case shortLine(Int)
var description: String { get }
}
/// A route that runs on less of a stretch than this, m, only crosses it, unless it runs on all of the stretch.
let wetlandMinOnM: Double
/// Offline: the stretches through OSM wetland a route line runs on, from an offline pack's wetlands.geojson, in route
/// order. The stretch is cut in pieces of at most matchM; a piece is on the route when both its ends lie within
/// matchM of the line. A stretch is on the route when its pieces on the route make at least wetlandMinOnM, or when
/// all of it is on the route. Throws WetlandsError for a line under 2 points.
func wetlandsOnRoute(_ wetlands: PackWetlands, line: [LonLat]) throws -> RouteWetlands