Address GeoCoder Canada C# Rest Snippet

using System.Web;


namespace address_geocode_canada_dot_net.REST
{
    /// <summary>
    /// Provides functionality to call the ServiceObjects Address Geocode CA (AGCA) REST API's GetGeoLocation endpoint,
    /// retrieving geocoding information (e.g., latitude, longitude, postal code) for a given Canadian address with fallback to a backup endpoint
    /// for reliability in live mode.
    /// </summary>
    public static class GetGeoLocationClient
    {
        private const string LiveBaseUrl = "https://sws.serviceobjects.com/GCC/api.svc/json/";
        private const string BackupBaseUrl = "https://swsbackup.serviceobjects.com/GCC/api.svc/json/";
        private const string TrialBaseUrl = "https://trial.serviceobjects.com/GCC/api.svc/json/";

        /// <summary>
        /// Synchronously calls the GetGeoLocation REST endpoint to retrieve geocoding information,
        /// attempting the primary endpoint first and falling back to the backup if the response is invalid
        /// (Error.Number == "4") in live mode.
        /// </summary>
        /// <param name="input">The input parameters including address, municipality, province, postal code, and license key.</param>
        /// <returns>Deserialized <see cref="GetGeoLocationResponse"/> containing geocoding data or an error.</returns>
        public static GetGeoLocationResponse Invoke(GetGeoLocationInput input)
        {
            // Use query string parameters so missing/optional fields don't break the URL
            string url = BuildUrl(input, input.IsLive ? LiveBaseUrl : TrialBaseUrl);
            GetGeoLocationResponse response = Helper.HttpGet<GetGeoLocationResponse>(url, input.TimeoutSeconds);

            // Fallback on error in live mode
            if (input.IsLive && !IsValid(response))
            {
                string fallbackUrl = BuildUrl(input, BackupBaseUrl);
                GetGeoLocationResponse fallbackResponse = Helper.HttpGet<GetGeoLocationResponse>(fallbackUrl, input.TimeoutSeconds);
                return fallbackResponse;
            }

            return response;
        }

        /// <summary>
        /// Asynchronously calls the GetGeoLocation REST endpoint to retrieve geocoding information,
        /// attempting the primary endpoint first and falling back to the backup if the response is invalid
        /// (Error.Number == "4") in live mode.
        /// </summary>
        /// <param name="input">The input parameters including address, municipality, province, postal code, and license key.</param>
        /// <returns>Deserialized <see cref="GetGeoLocationResponse"/> containing geocoding data or an error.</returns>
        public static async Task<GetGeoLocationResponse> InvokeAsync(GetGeoLocationInput input)
        {
            // Use query string parameters so missing/optional fields don't break the URL
            string url = BuildUrl(input, input.IsLive ? LiveBaseUrl : TrialBaseUrl);
            GetGeoLocationResponse response = await Helper.HttpGetAsync<GetGeoLocationResponse>(url, input.TimeoutSeconds).ConfigureAwait(false);

            // Fallback on error in live mode
            if (input.IsLive && !IsValid(response))
            {
                string fallbackUrl = BuildUrl(input, BackupBaseUrl);
                GetGeoLocationResponse fallbackResponse = await Helper.HttpGetAsync<GetGeoLocationResponse>(fallbackUrl, input.TimeoutSeconds).ConfigureAwait(false);
                return fallbackResponse;
            }

            return response;
        }

        // Build the full request URL, including URL-encoded query string
        public static string BuildUrl(GetGeoLocationInput input, string baseUrl)
        {
            // Construct query string with URL-encoded parameters
            string qs = $"GetGeoLocation?" +
                        $"Address={HttpUtility.UrlEncode(input.Address)}" +
                        $"&Municipality={HttpUtility.UrlEncode(input.Municipality)}" +
                        $"&Province={HttpUtility.UrlEncode(input.Province)}" +
                        $"&PostalCode={HttpUtility.UrlEncode(input.PostalCode)}" +
                        $"&LicenseKey={HttpUtility.UrlEncode(input.LicenseKey)}";
            return baseUrl + qs;
        }

        private static bool IsValid(GetGeoLocationResponse response) => response?.Error == null || response.Error.Number != "4";

        /// <summary>
        /// Input parameters for the GetGeoLocation API call. Represents a Canadian address to geocode
        /// and returns latitude, longitude, postal code, and match code with cascading logic for partial matches.
        /// </summary>
        /// <param name="Address">Address line of the address to geocode (e.g., "124 Main Street"). Required.</param>
        /// <param name="Municipality">The municipality of the address to geocode (e.g., "Cayuga"). Optional if postal code is provided.</param>
        /// <param name="Province">The province of the address to geocode (e.g., "ON"). Optional if postal code is provided.</param>
        /// <param name="PostalCode">The postal code of the address to geocode. Optional if municipality and province are provided.</param>
        /// <param name="LicenseKey">The license key to authenticate the API request.</param>
        /// <param name="IsLive">Indicates whether to use the live service (true) or trial service (false).</param>
        /// <param name="TimeoutSeconds">Timeout duration for the API call, in seconds.</param>
        public record GetGeoLocationInput(
             string Address = "",
             string Municipality = "",
             string Province = "",
             string PostalCode = "",
             string LicenseKey = "",
             bool IsLive = true,
             int TimeoutSeconds = 15
        );
    }
}



using System.Runtime.Serialization;

namespace address_geocode_canada_dot_net.REST
{
    /// <summary>
    /// Response from GetGeoLocation API, containing the latitude, longitude, postal code, 
    /// and match code for the given Canadian address.
    /// </summary>
    [DataContract]
    public class GetGeoLocationResponse
    {
        public string Latitude { get; set; }
        public string Longitude { get; set; }
        public string PostalCode { get; set; }
        public string MatchCode { get; set; }
        public Error Error { get; set; }

        public override string ToString()
        {
            return $"Latitude: {Latitude}\n" +
                   $"Longitude: {Longitude}\n" +
                   $"PostalCode: {PostalCode}\n" +
                   $"MatchCode: {MatchCode}\n" +
                   $"Error: {(Error != null ? Error.ToString() : "null")}";
        }
    }

    [DataContract]
    public class GetPostalCodeInfoResponse
    {
        public string Latitude { get; set; }
        public string Longitude { get; set; }
        public string PostalCode { get; set; }
        public string TimeZone { get; set; }
        public string DST { get; set; }
        public string AreaCode { get; set; }
        public string City { get; set; }
        public string CityPopulation { get; set; }
        public string Province { get; set; }
        public Error Error { get; set; }

        public override string ToString()
        {
            return $"Latitude: {Latitude}\n" +
                   $"Longitude: {Longitude}\n" +
                   $"PostalCode: {PostalCode}\n" +
                   $"TimeZone: {TimeZone}\n" +
                   $"DST: {DST}\n" +
                   $"AreaCode: {AreaCode}\n" +
                   $"City: {City}\n" +
                   $"CityPopulation: {CityPopulation}\n" +
                   $"Province: {Province}\n" +
                   $"Error: {(Error != null ? Error.ToString() : "null")}";
        }
    }

    /// <summary>
    /// Response from GetGeoLocationByMunicipalityProvince API, containing the latitude, longitude, 
    /// postal code, and error for the given Canadian municipality and province.
    /// </summary>
    [DataContract]
    public class GetGeoLocationByMunicipalityProvinceResponse
    {
        public string Latitude { get; set; }
        public string Longitude { get; set; }
        public string PostalCode { get; set; }
        public Error Error { get; set; }
        public override string ToString()
        {
            return $"Latitude: {Latitude}\n" +
                   $"Longitude: {Longitude}\n" +
                   $"PostalCode: {PostalCode}\n" +
                   $"Error: {(Error != null ? Error.ToString() : "null")}";
        }
    }

    /// <summary>
    /// Error object for API responses
    /// </summary>
    [DataContract]
    public class Error
    {
        public string Desc { get; set; }
        public string Number { get; set; }

        public string Location { get; set; }

        public override string ToString()
        {
            return $"Desc: {Desc}, Number: {Number}, Location: {Location}";
        }
    }
}

using System.Text.Json;
using System.Web;

namespace address_geocode_canada_dot_net.REST
{
    public class Helper
    {
        public static T HttpGet<T>(string url, int timeoutSeconds)
        {
            using var httpClient = new HttpClient
            {
                Timeout = TimeSpan.FromSeconds(timeoutSeconds)
            };
            using var request = new HttpRequestMessage(HttpMethod.Get, url);
            using HttpResponseMessage response = httpClient
                .SendAsync(request)
                .GetAwaiter()
                .GetResult();
            response.EnsureSuccessStatusCode();
            using Stream responseStream = response.Content
                .ReadAsStreamAsync()
                .GetAwaiter()
                .GetResult();
            var options = new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true
            };
            object? obj = JsonSerializer.Deserialize(responseStream, typeof(T), options);
            T result = (T)obj!;
            return result;
        }

        // Asynchronous HTTP GET and JSON deserialize
        public static async Task<T> HttpGetAsync<T>(string url, int timeoutSeconds)
        {
            HttpClient HttpClient = new HttpClient();
            HttpClient.Timeout = TimeSpan.FromSeconds(timeoutSeconds);
            using var httpResponse = await HttpClient.GetAsync(url).ConfigureAwait(false);
            httpResponse.EnsureSuccessStatusCode();
            var stream = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
            return JsonSerializer.Deserialize<T>(stream)!;
        }

        public static string UrlEncode(string value) => HttpUtility.UrlEncode(value ?? string.Empty);
    }
}

Address GeoCoder Canada Python Code Snippet

import requests
from agca_response import GetGeoLocationResponse, Error

# Endpoint URLs for ServiceObjects Address Geocode CA (AGCA) API
primary_url = "https://sws.serviceobjects.com/GCC/api.svc/json/GetGeoLocation?"
backup_url = "https://swsbackup.serviceobjects.com/GCC/api.svc/json/GetGeoLocation?"
trial_url = "https://trial.serviceobjects.com/GCC/api.svc/json/GetGeoLocation?"

def get_geo_location(
    address: str,
    municipality: str,
    province: str,
    postal_code: str,
    license_key: str,
    is_live: bool = True
) -> GetGeoLocationResponse:
    """
    Call ServiceObjects Address Geocode CA (AGCA) API's GetGeoLocation endpoint
    to retrieve geocoding information (latitude, longitude, postal code, match code) for a given Canadian address.

    Parameters:
        address: Address line of the address to geocode (e.g., "123 Main Street").
        municipality: The municipality of the address to geocode (e.g., "Cayuga").
        province: The province of the address to geocode (e.g., "ON").
        postal_code: The postal code of the address to geocode (e.g., "N0A 1E0").
        license_key: Your ServiceObjects license key.
        is_live: Use live or trial servers.

    Returns:
        GetGeoLocationResponse: Parsed JSON response with geocoding results or error details.

    Raises:
        RuntimeError: If the API returns an error payload.
        requests.RequestException: On network/HTTP failures (trial mode).
    """
    params = {
        "Address": address,
        "Municipality": municipality,
        "Province": province,
        "PostalCode": postal_code,
        "LicenseKey": license_key,
    }
    # Select the base URL: production vs trial
    url = primary_url if is_live else trial_url

    try:
        # Attempt primary (or trial) endpoint
        response = requests.get(url, params=params, timeout=10)
        response.raise_for_status()
        data = response.json()

        # If API returned an error in JSON payload, trigger fallback
        error = data.get('Error', None)
        if not (error is None or error.get('Number', None) != "4"):
            if is_live:
                # Try backup URL
                response = requests.get(backup_url, params=params, timeout=10)
                response.raise_for_status()
                data = response.json()

                # If still error, propagate exception
                if 'Error' in data:
                    raise RuntimeError(f"AGCA service error: {data['Error']}")

        # Convert JSON response to GetGeoLocationResponse for structured access
        error = Error(**data.get("Error", {})) if data.get("Error") else None

        return GetGeoLocationResponse(
            Latitude=data.get("Latitude"),
            Longitude=data.get("Longitude"),
            PostalCode=data.get("PostalCode"),
            MatchCode=data.get("MatchCode"),
            Error=error,
        )

    except requests.RequestException as req_exc:
        # Network or HTTP-level error occurred
        if is_live:
            try:
                # Fallback to backup URL
                response = requests.get(backup_url, params=params, timeout=10)
                response.raise_for_status()
                data = response.json()
                if "Error" in data:
                    raise RuntimeError(f"AGCA backup error: {data['Error']}") from req_exc

                error = Error(**data.get("Error", {})) if data.get("Error") else None

                return GetGeoLocationResponse(
                    Latitude=data.get("Latitude"),
                    Longitude=data.get("Longitude"),
                    PostalCode=data.get("PostalCode"),
                    MatchCode=data.get("MatchCode"),
                    Error=error,
                )
            except Exception as backup_exc:
                raise RuntimeError("AGCA service unreachable on both endpoints") from backup_exc
        else:
            raise RuntimeError(f"AGCA trial error: {str(req_exc)}") from req_exc


from dataclasses import dataclass
from typing import Optional

@dataclass
class GetGeoLocationInput:
    Address: Optional[str] = None
    Municipality: Optional[str] = None
    Province: Optional[str] = None
    PostalCode: Optional[str] = None
    LicenseKey: Optional[str] = None
    IsLive: bool = True
    TimeoutSeconds: int = 15

    def __str__(self) -> str:
        return (f"GetGeoLocationInput: Address={self.Address}, Municipality={self.Municipality}, "
                f"Province={self.Province}, PostalCode={self.PostalCode}, LicenseKey={self.LicenseKey}, "
                f"IsLive={self.IsLive}, TimeoutSeconds={self.TimeoutSeconds}")

@dataclass
class GetPostalCodeInfoInput:
    PostalCode: Optional[str] = None
    LicenseKey: Optional[str] = None
    IsLive: bool = True
    TimeoutSeconds: int = 15

    def __str__(self) -> str:
        return (f"GetPostalCodeInfoInput: PostalCode={self.PostalCode}, LicenseKey={self.LicenseKey}, "
                f"IsLive={self.IsLive}, TimeoutSeconds={self.TimeoutSeconds}")

@dataclass
class GetGeoLocationByMunicipalityProvinceInput:
    Municipality: Optional[str] = None
    Province: Optional[str] = None
    LicenseKey: Optional[str] = None
    IsLive: bool = True
    TimeoutSeconds: int = 15

    def __str__(self) -> str:
        return (f"GetGeoLocationByMunicipalityProvinceInput: Municipality={self.Municipality}, "
                f"Province={self.Province}, LicenseKey={self.LicenseKey}, "
                f"IsLive={self.IsLive}, TimeoutSeconds={self.TimeoutSeconds}")

@dataclass
class Error:
    Desc: Optional[str] = None
    Number: Optional[str] = None
    Location: Optional[str] = None

    def __str__(self) -> str:
        return f"Error: Desc={self.Desc}, Number={self.Number}, Location={self.Location}"

@dataclass
class GetGeoLocationResponse:
    Latitude: Optional[str] = None
    Longitude: Optional[str] = None
    PostalCode: Optional[str] = None
    MatchCode: Optional[str] = None
    Error: Optional['Error'] = None

    def __str__(self) -> str:
        error = str(self.Error) if self.Error else 'None'
        return (f"GetGeoLocationResponse: Latitude={self.Latitude}, Longitude={self.Longitude}, "
                f"PostalCode={self.PostalCode}, MatchCode={self.MatchCode}, Error={error}")

@dataclass
class GetPostalCodeInfoResponse:
    Latitude: Optional[str] = None
    Longitude: Optional[str] = None
    PostalCode: Optional[str] = None
    TimeZone: Optional[str] = None
    DST: Optional[str] = None
    AreaCode: Optional[str] = None
    City: Optional[str] = None
    CityPopulation: Optional[str] = None
    Province: Optional[str] = None
    Error: Optional['Error'] = None

    def __str__(self) -> str:
        error = str(self.Error) if self.Error else 'None'
        return (f"GetPostalCodeInfoResponse: Latitude={self.Latitude}, Longitude={self.Longitude}, "
                f"PostalCode={self.PostalCode}, TimeZone={self.TimeZone}, DST={self.DST}, "
                f"AreaCode={self.AreaCode}, City={self.City}, CityPopulation={self.CityPopulation}, "
                f"Province={self.Province}, Error={error}")

@dataclass
class GetGeoLocationByMunicipalityProvinceResponse:
    Latitude: Optional[str] = None
    Longitude: Optional[str] = None
    PostalCode: Optional[str] = None
    Error: Optional['Error'] = None

    def __str__(self) -> str:
        error = str(self.Error) if self.Error else 'None'
        return (f"GetGeoLocationByMunicipalityProvinceResponse: Latitude={self.Latitude}, "
                f"Longitude={self.Longitude}, PostalCode={self.PostalCode}, Error={error}")

Address GeoCoder Canada NodeJS Code Snippet

import axios from 'axios';
import querystring from 'querystring';
import { GetGeoLocationResponse } from './agca_response.js';

/**
 * @constant
 * @type {string}
 * @description The base URL for the live ServiceObjects Address Geocode CA (AGCA) API service.
 */
const LiveBaseUrl = 'https://sws.serviceobjects.com/GCC/api.svc/json/';

/**
 * @constant
 * @type {string}
 * @description The base URL for the backup ServiceObjects Address Geocode CA (AGCA) API service.
 */
const BackupBaseUrl = 'https://swsbackup.serviceobjects.com/GCC/api.svc/json/';

/**
 * @constant
 * @type {string}
 * @description The base URL for the trial ServiceObjects Address Geocode CA (AGCA) API service.
 */
const TrialBaseUrl = 'https://trial.serviceobjects.com/GCC/api.svc/json/';

/**
 * <summary>
 * Checks if a response from the API is valid by verifying that it either has no Error object
 * or the Error.Number is not equal to '4'.
 * </summary>
 * <param name="response" type="Object">The API response object to validate.</param>
 * <returns type="boolean">True if the response is valid, false otherwise.</returns>
 */
const isValid = (response) => !response?.Error || response.Error.Number !== '4';

/**
 * <summary>
 * Constructs a full URL for the GetGeoLocation API endpoint by combining the base URL
 * with query parameters derived from the input parameters.
 * </summary>
 * <param name="params" type="Object">An object containing all the input parameters.</param>
 * <param name="baseUrl" type="string">The base URL for the API service (live, backup, or trial).</param>
 * <returns type="string">The constructed URL with query parameters.</returns>
 */
const buildUrl = (params, baseUrl) =>
    `${baseUrl}GetGeoLocation?${querystring.stringify(params)}`;

/**
 * <summary>
 * Performs an HTTP GET request to the specified URL with a given timeout.
 * </summary>
 * <param name="url" type="string">The URL to send the GET request to.</param>
 * <param name="timeoutSeconds" type="number">The timeout duration in seconds for the request.</param>
 * <returns type="Promise<GetGeoLocationResponse>">A promise that resolves to a GetGeoLocationResponse object containing the API response data.</returns>
 * <exception cref="Error">Thrown if the HTTP request fails, with a message detailing the error.</exception>
 */
const httpGet = async (url, timeoutSeconds) => {
    try {
        const response = await axios.get(url, { timeout: timeoutSeconds * 1000 });
        return new GetGeoLocationResponse(response.data);
    } catch (error) {
        throw new Error(`HTTP request failed: ${error.message}`);
    }
};

/**
 * <summary>
 * Provides functionality to call the ServiceObjects Address Geocode CA (AGCA) API's GetGeoLocation endpoint,
 * retrieving geocoding information (e.g., latitude, longitude, postal code) for a given Canadian address with fallback to a backup endpoint for reliability in live mode.
 * </summary>
 */
const GetGeoLocationClient = {
    /**
     * <summary>
     * Asynchronously invokes the GetGeoLocation API endpoint, attempting the primary endpoint
     * first and falling back to the backup if the response is invalid (Error.Number == '4') in live mode.
     * </summary>
     * @param {string} Address - Address line of the address to geocode (e.g., "123 Main Street"). Required.
     * @param {string} Municipality - The municipality of the address to geocode (e.g., "Cayuga"). Optional if postal code is provided.
     * @param {string} Province - The province of the address to geocode (e.g., "ON"). Optional if postal code is provided.
     * @param {string} PostalCode - The postal code of the address to geocode. Optional if municipality and province are provided.
     * @param {string} LicenseKey - Your license key to use the service.
     * @param {boolean} IsLive - Value to determine whether to use the live or trial servers.
     * @param {number} TimeoutSeconds - Timeout, in seconds, for the call to the service.
     * @returns {Promise<GetGeoLocationResponse>} - A promise that resolves to a GetGeoLocationResponse object.
     */
    async invokeAsync(Address, Municipality, Province, PostalCode, LicenseKey, IsLive = true, TimeoutSeconds = 15) {
        const params = {
            Address,
            Municipality,
            Province,
            PostalCode,
            LicenseKey: LicenseKey
        };

        const url = buildUrl(params, IsLive ? LiveBaseUrl : TrialBaseUrl);
        let response = await httpGet(url, TimeoutSeconds);

        if (IsLive && !isValid(response)) {
            const fallbackUrl = buildUrl(params, BackupBaseUrl);
            const fallbackResponse = await httpGet(fallbackUrl, TimeoutSeconds);
            return fallbackResponse;
        }
        return response;
    },

    /**
     * <summary>
     * Synchronously invokes the GetGeoLocation API endpoint by wrapping the async call
     * and awaiting its result immediately.
     * </summary>
     * @param {string} Address - Address line of the address to geocode (e.g., "123 Main Street"). Required.
     * @param {string} Municipality - The municipality of the address to geocode (e.g., "Cayuga"). Optional if postal code is provided.
     * @param {string} Province - The province of the address to geocode (e.g., "ON"). Optional if postal code is provided.
     * @param {string} PostalCode - The postal code of the address to geocode. Optional if municipality and province are provided.
     * @param {string} LicenseKey - Your license key to use the service.
     * @param {boolean} IsLive - Value to determine whether to use the live or trial servers.
     * @param {number} TimeoutSeconds - Timeout, in seconds, for the call to the service.
     * @returns {GetGeoLocationResponse} - A GetGeoLocationResponse object with geocoding details or an error.
     */
    invoke(Address, Municipality, Province, PostalCode, LicenseKey, IsLive = true, TimeoutSeconds = 15) {
        return (async () => await this.invokeAsync(Address, Municipality, Province, PostalCode, LicenseKey, IsLive, TimeoutSeconds))();
    }
};

export { GetGeoLocationClient, GetGeoLocationResponse };


/**
 * Input parameters for the GetGeoLocation API call.
 */
export class GetGeoLocationInput {
    constructor(data = {}) {
        this.Address = data.Address;
        this.Municipality = data.Municipality;
        this.Province = data.Province;
        this.PostalCode = data.PostalCode;
        this.LicenseKey = data.LicenseKey;
        this.IsLive = data.IsLive !== undefined ? data.IsLive : true;
        this.TimeoutSeconds = data.TimeoutSeconds !== undefined ? data.TimeoutSeconds : 15;
    }

    toString() {
        return `GetGeoLocationInput: Address = ${this.Address}, Municipality = ${this.Municipality}, Province = ${this.Province}, PostalCode = ${this.PostalCode}, LicenseKey = ${this.LicenseKey}, IsLive = ${this.IsLive}, TimeoutSeconds = ${this.TimeoutSeconds}`;
    }
}

/**
 * Input parameters for the GetPostalCodeInfo API call.
 */
export class GetPostalCodeInfoInput {
    constructor(data = {}) {
        this.PostalCode = data.PostalCode;
        this.LicenseKey = data.LicenseKey;
        this.IsLive = data.IsLive !== undefined ? data.IsLive : true;
        this.TimeoutSeconds = data.TimeoutSeconds !== undefined ? data.TimeoutSeconds : 15;
    }

    toString() {
        return `GetPostalCodeInfoInput: PostalCode = ${this.PostalCode}, LicenseKey = ${this.LicenseKey}, IsLive = ${this.IsLive}, TimeoutSeconds = ${this.TimeoutSeconds}`;
    }
}

/**
 * Input parameters for the GetGeoLocationByMunicipalityProvince API call.
 */
export class GetGeoLocationByMunicipalityProvinceInput {
    constructor(data = {}) {
        this.Municipality = data.Municipality;
        this.Province = data.Province;
        this.LicenseKey = data.LicenseKey;
        this.IsLive = data.IsLive !== undefined ? data.IsLive : true;
        this.TimeoutSeconds = data.TimeoutSeconds !== undefined ? data.TimeoutSeconds : 15;
    }

    toString() {
        return `GetGeoLocationByMunicipalityProvinceInput: Municipality = ${this.Municipality}, Province = ${this.Province}, LicenseKey = ${this.LicenseKey}, IsLive = ${this.IsLive}, TimeoutSeconds = ${this.TimeoutSeconds}`;
    }
}

/**
 * Error object for API responses.
 */
export class Error {
    constructor(data = {}) {
        this.Desc = data.Desc;
        this.Number = data.Number;
        this.Location = data.Location;
    }

    toString() {
        return `Error: Desc = ${this.Desc}, Number = ${this.Number}, Location = ${this.Location}`;
    }
}

/**
 * Response from GetGeoLocation API, containing the latitude, longitude, postal code, 
 * and match code for the given Canadian address.
 */
export class GetGeoLocationResponse {
    constructor(data = {}) {
        this.Latitude = data.Latitude;
        this.Longitude = data.Longitude;
        this.PostalCode = data.PostalCode;
        this.MatchCode = data.MatchCode;
        this.Error = data.Error ? new Error(data.Error) : null;
    }

    toString() {
        return `GetGeoLocationResponse: Latitude = ${this.Latitude}, Longitude = ${this.Longitude}, PostalCode = ${this.PostalCode}, MatchCode = ${this.MatchCode}, Error = ${this.Error ? this.Error.toString() : 'null'}`;
    }
}

/**
 * Response from GetPostalCodeInfo API, containing the latitude, longitude, postal code, 
 * time zone, DST, area code, city, city population, province, and error for the given Canadian postal code.
 */
export class GetPostalCodeInfoResponse {
    constructor(data = {}) {
        this.Latitude = data.Latitude;
        this.Longitude = data.Longitude;
        this.PostalCode = data.PostalCode;
        this.TimeZone = data.TimeZone;
        this.DST = data.DST;
        this.AreaCode = data.AreaCode;
        this.City = data.City;
        this.CityPopulation = data.CityPopulation;
        this.Province = data.Province;
        this.Error = data.Error ? new Error(data.Error) : null;
    }

    toString() {
        return `GetPostalCodeInfoResponse: Latitude = ${this.Latitude}, Longitude = ${this.Longitude}, PostalCode = ${this.PostalCode}, TimeZone = ${this.TimeZone}, DST = ${this.DST}, AreaCode = ${this.AreaCode}, City = ${this.City}, CityPopulation = ${this.CityPopulation}, Province = ${this.Province}, Error = ${this.Error ? this.Error.toString() : 'null'}`;
    }
}

/**
 * Response from GetGeoLocationByMunicipalityProvince API, containing the latitude, longitude, 
 * postal code, and error for the given Canadian municipality and province.
 */
export class GetGeoLocationByMunicipalityProvinceResponse {
    constructor(data = {}) {
        this.Latitude = data.Latitude;
        this.Longitude = data.Longitude;
        this.PostalCode = data.PostalCode;
        this.Error = data.Error ? new Error(data.Error) : null;
    }

    toString() {
        return `GetGeoLocationByMunicipalityProvinceResponse: Latitude = ${this.Latitude}, Longitude = ${this.Longitude}, PostalCode = ${this.PostalCode}, Error = ${this.Error ? this.Error.toString() : 'null'}`;
    }
}

export default GetGeoLocationResponse;