/** * ParkSmarter API data models. * * Two casing worlds exist: * - This client's *inputs* use friendly camelCase (see the `*Params` types). * - The server speaks PascalCase ("PSJSON"). Response models below therefore use * the exact server field spellings recovered from the app. Response interfaces * carry an index signature because not every field is guaranteed on every call; * the well-known fields are typed explicitly. Run a live capture to lock down * the optional tail for a given endpoint if you need exhaustiveness. */ /** * The common status/token-refresh envelope embedded in most authenticated * responses as `Response`. `Auth_Token` here is usually null but, when present, * is a rolling refresh of the user token (the client stores it automatically). * CONFIRMED via live capture. */ export interface ResponseEnvelope { Auth_Token: string | null; Message: string | null; Status: string | null; } /** * Casing note (CONFIRMED via live capture): the meter/zone *response* uses * `ZoneId` / `SpaceId` / `CustomerId` (lowercase "d"), while estimate & session * *requests* expect `ZoneID` / `SpaceID` / `CustomerID` (capital "ID"). When you * feed a captured Zone into an estimate/session, read `zone.CustomerId` / * `space.SpaceId` and pass them as the client's camelCase params — the client * emits the capital-ID request spelling for you. */ /* ------------------------------------------------------------------ */ /* Auth & account */ /* ------------------------------------------------------------------ */ export interface LoginWithPhoneParams { /** Phone number, digits only (no country code prefix). */ phoneNumber: string; password: string; } export interface LoginWithAppleParams { emailAddress: string; appleId: string; providerAuth: string; providerIdentity: string; } /** * POST /api/Auth response (login). CONFIRMED: `{ Status, Message, Auth_Token }`. * Auth_Token is persisted automatically; SessionId is delivered separately (by * bootstrap / headers) and also persisted. */ export interface AuthResponse { Status?: string; Message?: string; Auth_Token?: string; [key: string]: unknown; } export interface SignUpParams { emailAddress: string; /** Phone number, digits only. */ mobilePhone: string; password: string; } export interface RequestResetPasswordParams { /** Server `ResetPasswordType`; the app passes a numeric/string reason code. */ reqType: string | number; /** Phone number, digits only. */ phoneNumber: string; } export interface UpdatePasswordParams { oldPassword: string; newPassword: string; } export interface UpdateProfileParams { emailAddress: string; /** Phone number, digits only. */ phoneNumber: string; } export interface RequestVerifyUserParams { /** Phone number, digits only. The client prefixes country code "1". */ phoneNumber: string; } export interface VerifyUserParams { /** Phone number, digits only. The client prefixes country code "1". */ phoneNumber: string; /** SMS confirmation code. */ code: string; } export interface UpdateDeviceTokenParams { /** Push token (server field `DeviceID`). */ pushNotificationsToken: string; imeiNumber?: string; /** Defaults to '1' (Android) as the app hardcodes. */ deviceType?: string; /** BCP-47 language, defaults to the client locale. */ language?: string; } export interface UpdateDeviceTokenResponse { Status?: string; Message?: string; [key: string]: unknown; } /** GET /api/User response. CONFIRMED via live capture. */ export interface UserDetail { PersonalEmailAddress?: string; /** Digits-only phone as a string. */ PersonalPhone?: string; VehicleDetails?: VehicleDetail[]; CreditCardDetails?: CreditCardDetail[]; /** Numeric flag (0/1), not a boolean. */ OffersOptIn?: number; [key: string]: unknown; } /* ------------------------------------------------------------------ */ /* Vehicles */ /* ------------------------------------------------------------------ */ /** CONFIRMED via live capture. Note `IsDefault` is a string ("true"/"false"), not a boolean. */ export interface VehicleDetail { VehicleID?: number; VehiclePlate?: string; VehicleState?: string; VehicleAlias?: string; /** Server returns this as a string, e.g. "true" / "false". */ IsDefault?: string; /** Per-item status fields, usually null on reads. */ Status?: string | null; Message?: string | null; [key: string]: unknown; } export interface AddVehicleParams { plate: string; state: string; vehicleAlias?: string; isDefaultVehicle?: boolean; } export interface UpdateVehicleParams extends AddVehicleParams { id: number | string; } export interface VehicleMutationResponse { Status?: string; [key: string]: unknown; } /* ------------------------------------------------------------------ */ /* Credit cards */ /* ------------------------------------------------------------------ */ /** * CONFIRMED via live capture. The PAN is never returned — only `CCFirstSix` + * `CCLastFour`. `CCDefault` comes back as a string ("true"/"false"). Note the * response uses `ParentPBPCardId`, whereas the add/update *request* uses `ParentCCID`. */ export interface CreditCardDetail { CCID?: number; CCAlias?: string; /** First 6 digits (BIN), numeric string. */ CCFirstSix?: string; /** Last 4 digits, numeric string. */ CCLastFour?: string; CCExpDate?: string; CCZip?: string; /** String "true"/"false", not a boolean. */ CCDefault?: string; ParentPBPCardId?: number | null; /** Per-item status fields, usually null on reads. */ Status?: string | null; Message?: string | null; [key: string]: unknown; } export interface AddCardParams { cardNumber: string; alias?: string; /** Expiry, format as the app sends it (e.g. "MM/YY"). */ expDate: string; zipCode: string; isDefaultCard?: boolean; /** Present when editing an existing card (server `ParentCCID`). */ id?: number | string; } export interface SetDefaultCardParams { id: number | string; isDefaultCard: boolean; } /* ------------------------------------------------------------------ */ /* Meters / zones */ /* ------------------------------------------------------------------ */ export interface LatLng { latitude: number; longitude: number; } /** A rate/time policy slot within a space. CONFIRMED via live capture. */ export interface SpacePolicy { CurrentSlot?: boolean; DayNumber?: number; DisplayString?: string; StartDateTime?: string; EndDateTime?: string; StartTimeDisplay?: string; EndTimeDisplay?: string; EventRateFlag?: boolean; MaxTime?: number; MessageHeader?: string; MessageText?: string; Rate?: number; RateType?: string; [key: string]: unknown; } /** * A single space within a zone. CONFIRMED via live capture. * Note the id is `SpaceId` (lowercase "d") here; estimate/session requests want * the capital-ID `SpaceID` (the client maps camelCase params to that spelling). */ export interface Space { SpaceId?: number; SpaceName?: string; SSPMSpaceId?: number; MeterPurchaseType?: number; OccupancyStatus?: number; Policies?: SpacePolicy[]; [key: string]: unknown; } /** * A parking zone/meter as returned inside `Zones`. CONFIRMED via live capture. * `ScannerCode` is the value encoded in kiosk QR codes; `TerminalSerNo` is the * printed serial. Both drive the scan / lookup features. */ export interface Zone { ZoneId?: number; ZoneGuid?: string; ZoneName?: string; ZoneLocation?: string; ZonePlates?: unknown; /** Printed serial number (numeric string). */ TerminalSerNo?: string; /** QR-encoded scanner code. */ ScannerCode?: string; Lat?: number; Long?: number; CustomerId?: number; CustomerName?: string; /** Minutes offset / IANA-less numeric zone id as returned. */ TimeZone?: number; DSTAdjust?: number; CityLogo?: string; DepartmentLogo?: string; BackgroundColor?: string; /** Returned as a numeric string. */ ForegroundColor?: string; MinimumAmount?: number; MaxTime?: number; MeterType?: string; MeterTypeId?: number; /** Base rate, returned as a string. */ Rate?: string; ProgressiveRate?: number; PercentageFull?: number; IsAllowOverAir?: boolean; IsAllowBLE?: boolean; IsExtension?: boolean; IsPaid?: boolean; Spaces?: Space[]; [key: string]: unknown; } /** GET /api/Meter and /api/MeterList. CONFIRMED via live capture. */ export interface MetersResponse { Zones?: Zone[] | null; Response?: ResponseEnvelope; [key: string]: unknown; } /* ------------------------------------------------------------------ */ /* Parking lots (ParkingLogix) */ /* ------------------------------------------------------------------ */ /** One level/section within a ParkingLogix lot. CONFIRMED via live capture. */ export interface ParkingLotDetail { ParkingLogixLotDetailId?: number; ParkingLogixLotId?: number; Level?: number; TotalSpaces?: number; FreeSpaces?: number; [key: string]: unknown; } /** CONFIRMED via live capture. Per-level occupancy lives in ParkingLogixLotDetails. */ export interface ParkingLot { ParkingLogixLotId?: number; LotName?: string; LocationAddress?: string; Lat?: number; Long?: number; TotalSpaces?: number; DefaultFree?: boolean; ParkingLogixLotDetails?: ParkingLotDetail[]; [key: string]: unknown; } export interface ParkingLotsResponse { ParkingLogixLots?: ParkingLot[] | null; Response?: ResponseEnvelope; [key: string]: unknown; } /* ------------------------------------------------------------------ */ /* Estimates */ /* ------------------------------------------------------------------ */ export interface MultiEstimateParams { zoneId: number | string; spaceId: number | string; customerId: number | string; /** Zone minimum credit (server `MinCreditAmount`). */ minCreditAmount?: number | string; vehicleId: number | string; /** Optional BLE encrypted bytes string. */ bleEncBytes?: string; } export interface SingleEstimateParams { zoneId: number | string; spaceId: number | string; customerId: number | string; /** Server `ParkingDuration`, in minutes. */ durationInMinutes: number; vehicleId: number | string; /** Server `CCID` — credit card id. */ creditCardId: number | string; } export interface ItemsEstimateParams { zoneId: number | string; spaceId: number | string; customerId: number | string; vehicleId: number | string; } /** * One priced duration option. CONFIRMED via live capture. * Money/id fields come back as numeric *strings* here. */ export interface ParkingDetail { Minutes?: number; StartTime?: string; EndTime?: string; ParkingCost?: string; TransactionFee?: string; CurrentAmountPaid?: number; CustomerID?: string; CustomerName?: string; Zone?: string; ZoneID?: string; Space?: string; SpaceID?: string; VehicleID?: string; VehicleNumber?: string | null; CCNumber?: string | null; PricingToken?: string | null; TimeZone?: number; DSTAdjust?: number; [key: string]: unknown; } /** GET /api/ParkingEstimateMulti. CONFIRMED via live capture (a full price ladder). */ export interface MultiEstimateResponse { ParkingDetail?: ParkingDetail[]; MinTime?: number; MaxTime?: number; TimeRemaining?: number; JumpRateEnabled?: boolean; JumpRateThreshold?: number; JumpRateSetValue?: number; Response?: ResponseEnvelope; [key: string]: unknown; } /** GET /api/ParkingEstimate. CONFIRMED via live capture (a single priced option). */ export interface SingleEstimateResponse { ParkingDetail?: ParkingDetail; MinTime?: number; MaxTime?: number; CurrentCustomerDateTime?: string; Response?: ResponseEnvelope; [key: string]: unknown; } /** GET /api/ParkingEstimateItems. CONFIRMED via live capture. */ export interface ItemsEstimateResponse { ZoneID?: number; ZoneName?: string; SpaceID?: number; SpaceName?: string; CustomerID?: number; CustomerName?: string; PurchaseMode?: string; Items?: unknown[] | null; TimeStampUTC?: number; TimeZone?: number; DSTAdjust?: number; Response?: ResponseEnvelope; [key: string]: unknown; } /* ------------------------------------------------------------------ */ /* Parking sessions */ /* ------------------------------------------------------------------ */ export interface StartParkingSessionParams { creditCardId: number | string; spaceId: number | string; customerId: number | string; zoneId: number | string; vehicleId: number | string; /** ISO/formatted start time as the server expects. */ startTime: string; endTime: string; /** Minutes purchased (server `TimePurchased`). */ minutesToPurchase: number; /** Base cost, dollars (server `ParkingCost`). */ parkingCost: number; /** Fee, dollars (server `TransactionFee`). Defaults to 0. */ transactionFee?: number; /** Zone minimum credit (server `MinCreditAmount`). */ minCreditAmount?: number; meterTypeId: number | string; /** Optional BLE encrypted bytes string. */ bleEncBytes?: string; } /** * POST /api/Session. CONFIRMED via live capture. Returns HTTP 200 even on a * declined charge — check `Response.Status === 'Error'` (the client does this and * throws). `OriginalErrorMessage` carries the gateway reason (e.g. "DECLINED"). */ export interface StartParkingSessionResponse { Response?: ResponseEnvelope; BleEncBytes?: string | null; PBPParkingSessionId?: number; OriginalErrorMessage?: string; StartTime?: string | null; EndTime?: string | null; TimePurchased?: string | null; ZoneID?: number | string | null; Zone?: string | null; SpaceID?: number | string | null; Space?: string | null; VehicleNumber?: string | null; Lat?: number | null; Long?: number | null; TransactionFee?: string | number | null; Amount?: string | number | null; AmountCharged?: string | number | null; [key: string]: unknown; } /** UNCONFIRMED element shape (no active sessions on the test account). */ export interface ActiveSession { TransactionID?: number | string; ZoneName?: string; SpaceName?: string; Space?: string; StartTime?: string; EndTime?: string; StartTimeDisplay?: string; EndTimeDisplay?: string; TimeRemaining?: number | string; VehiclePlate?: string; VehicleNumber?: string; Amount?: number | string; IsExtension?: boolean; [key: string]: unknown; } /** GET /api/ParkingSession. Envelope CONFIRMED; element shape UNCONFIRMED (no active sessions in test account). */ export interface ActiveSessionsResponse { ParkingSession?: ActiveSession[] | null; CurrentCustomerTime?: string | null; Response?: ResponseEnvelope; [key: string]: unknown; } /** CONFIRMED via a live DL-zone session (fields observed on GET /api/Session). */ export interface PastSession { TransactionID?: number | string; Zone?: string; ZoneID?: number | string; Space?: string; SpaceID?: number | string; StartTime?: string; EndTime?: string; TimePurchased?: number | string; VehicleNumber?: string; Amount?: number | string; TransactionFee?: number | string; CardFirstSix?: string; CardLastFour?: string; PaymentDisplay?: string; CustomerID?: number | string; CustomerName?: string; City?: string; Description?: string; MeterTypeId?: number; Lat?: number | string; Long?: number | string; IsFavorite?: boolean; FavoriteID?: number | string; Logo?: string; /** Legacy/alt field some views used; prefer `Zone`. */ ZoneName?: string; [key: string]: unknown; } /** GET /api/Session. Envelope CONFIRMED; element shape UNCONFIRMED (no past sessions in test account). */ export interface PastSessionsResponse { Session?: PastSession[] | null; Response?: ResponseEnvelope; [key: string]: unknown; } export interface PastSessionsParams { currentPage?: number | string; pageSize?: number | string; } /* ------------------------------------------------------------------ */ /* Receipts */ /* ------------------------------------------------------------------ */ /** CONFIRMED via a live DL-zone receipt (GET /api/ParkingReceipt). */ export interface ParkingReceipt { TransactionID?: number | string; CustomerID?: number | string; CustomerName?: string; Space?: string; SpaceID?: number | string; MeterNumber?: string; MeterTypeId?: number; StartTime?: string; EndTime?: string; PaymentType?: string; PaymentDisplay?: string; CardType?: string | null; /** Masked card, e.g. "****1234". */ CC?: string; AuthCode?: string; VehicleID?: number | string; Vehicle?: string; /** Display strings, e.g. "$0.10". */ Amount?: string; AmountCharged?: string; TransactionFee?: string; Total?: string; /** Numeric equivalents. */ AmountValue?: number; TransactionFeeValue?: number; TotalValue?: number; Logo?: string; BackgroundColor?: string; ForegroundColor?: string; ZoneName?: string; [key: string]: unknown; } export interface ReceiptResponse { ParkingReceipt?: ParkingReceipt; Response?: ResponseEnvelope; [key: string]: unknown; } /* ------------------------------------------------------------------ */ /* Notification settings */ /* ------------------------------------------------------------------ */ /** One toggle group within notification settings. */ export interface NotificationSetting { messagesEnabled?: boolean; emailsEnabled?: boolean; messages?: boolean; emails?: boolean; } /** Client-side view of the settings (server sends a numeric bitmask in `Settings`). */ export interface NotificationSettings { parkingReceipt?: NotificationSetting; overnight?: NotificationSetting; tenMin?: NotificationSetting; fifteenMin?: NotificationSetting; sessionEnded?: NotificationSetting; sessionStart?: NotificationSetting; } /** GET /api/Setting. CONFIRMED: `{ Response, Settings }`. */ export interface RawSettingsResponse { /** Server bitmask as a numeric string. Decode per the app's expandSettings logic. */ Settings?: string; Response?: ResponseEnvelope; [key: string]: unknown; } /** GET /api/State?ID=…. CONFIRMED wrapper `{ StatesResult }` (requires an ID; 404s without). */ export interface StatesResponse { StatesResult?: StateItem[]; [key: string]: unknown; } /* ------------------------------------------------------------------ */ /* Content / misc */ /* ------------------------------------------------------------------ */ /** Terms/Privacy/About all return `{ Value: string }`. */ export interface ValueResponse { Value?: string; [key: string]: unknown; } export interface FAQItem { Question?: string; Answer?: string; [key: string]: unknown; } export interface FAQResponse { FAQs?: FAQItem[]; [key: string]: unknown; } /** GET /api/ApplicationValidity — feature flags + maintenance + session bootstrap. */ export interface ApplicationValidityResponse { SessionId?: string; RecommendUpgrade?: boolean; ForceUpgrade?: boolean; IsParkingEstimateMultiEnabled?: boolean; Config?: { IsInMaintenanceMode?: boolean; ExtendedVariablePBPZoneIds?: unknown; ExtendedVariableRateMaxDayMinutes?: number; ExtendedVariableRateMaxDay?: number; ExtendedVariableMultiDayValueThreshold?: number; ExtendedVariableRateSingleHourRate?: number; ExtendedVariableRateMaxDayJump?: number; ExtendedVariableRateMaxDayValueDollar?: number; ExtendedVariableRateMaxMode?: unknown; UseLimitedMetersFetch?: boolean; UseLoadMetersButton?: boolean; UseReloadMetersOnResume?: boolean; UseApplePay?: boolean; UseGooglePay?: boolean; ApplePayHostAddress?: string; UseSearchBySpace?: boolean; [key: string]: unknown; }; [key: string]: unknown; } export interface StateItem { [key: string]: unknown; }