1Fetch Client API

<back to all web services

RequestQuote

The following routes are available for this service:
POST/quoteProvide waypoints for a route and return a quote.
import Foundation
import ServiceStack

public class RequestQuote : ApiServiceRequest, ILogRequest
{
    /**
    * Array of waypoints
    */
    // @ApiMember(Description="Array of waypoints", IsRequired=true)
    public var waypoints:[RequestQuoteWaypoint] = []

    /**
    * Is this a scheduled order?
    */
    // @ApiMember(Description="Is this a scheduled order?", IsRequired=true)
    public var isScheduled:Bool

    /**
    * Specify the scheduling type, required if IsScheduled is true
    */
    // @ApiMember(Description="Specify the scheduling type, required if IsScheduled is true")
    public var scheduleType:ScheduleType

    /**
    * Specify the scheduled date for this delivery in ISO 8601 string format, required if IsScheduled is true and ScheduleType is SpecificTime
    */
    // @ApiMember(Description="Specify the scheduled date for this delivery in ISO 8601 string format, required if IsScheduled is true and ScheduleType is SpecificTime")
    public var scheduledDate:String

    /**
    * Specify a quote Id to amend a quote. Required when amending an existing quote.
    */
    // @ApiMember(Description="Specify a quote Id to amend a quote. Required when amending an existing quote.")
    public var quoteId:String

    /**
    * Set this to true to prevent creating the quote
    */
    // @ApiMember(Description="Set this to true to prevent creating the quote", IsRequired=true)
    public var test:Bool

    required public init(){ super.init() }

    private enum CodingKeys : String, CodingKey {
        case waypoints
        case isScheduled
        case scheduleType
        case scheduledDate
        case quoteId
        case test
    }

    required public init(from decoder: Decoder) throws {
        try super.init(from: decoder)
        let container = try decoder.container(keyedBy: CodingKeys.self)
        waypoints = try container.decodeIfPresent([RequestQuoteWaypoint].self, forKey: .waypoints) ?? []
        isScheduled = try container.decodeIfPresent(Bool.self, forKey: .isScheduled)
        scheduleType = try container.decodeIfPresent(ScheduleType.self, forKey: .scheduleType)
        scheduledDate = try container.decodeIfPresent(String.self, forKey: .scheduledDate)
        quoteId = try container.decodeIfPresent(String.self, forKey: .quoteId)
        test = try container.decodeIfPresent(Bool.self, forKey: .test)
    }

    public override func encode(to encoder: Encoder) throws {
        try super.encode(to: encoder)
        var container = encoder.container(keyedBy: CodingKeys.self)
        if waypoints.count > 0 { try container.encode(waypoints, forKey: .waypoints) }
        if isScheduled != nil { try container.encode(isScheduled, forKey: .isScheduled) }
        if scheduleType != nil { try container.encode(scheduleType, forKey: .scheduleType) }
        if scheduledDate != nil { try container.encode(scheduledDate, forKey: .scheduledDate) }
        if quoteId != nil { try container.encode(quoteId, forKey: .quoteId) }
        if test != nil { try container.encode(test, forKey: .test) }
    }
}

public class ApiServiceRequest : IServiceRequest, IHasApiKey, Codable
{
    /**
    * The API Key required for authentication
    */
    // @ApiMember(DataType="string", Description="The API Key required for authentication", IsRequired=true)
    public var apiKey:String

    required public init(){}
}

public class RequestQuoteWaypoint : IRequestWaypoint, Codable
{
    /**
    * Number of waypoint for ordering
    */
    // @ApiMember(Description="Number of waypoint for ordering", IsRequired=true)
    public var waypointNumber:Int

    /**
    * Waypoint Latitude
    */
    // @ApiMember(Description="Waypoint Latitude", IsRequired=true)
    public var latitude:Double

    /**
    * Waypoint Longitude
    */
    // @ApiMember(Description="Waypoint Longitude", IsRequired=true)
    public var longitude:Double

    /**
    * Name of contact person at waypoint
    */
    // @ApiMember(Description="Name of contact person at waypoint", IsRequired=true)
    public var contactName:String

    /**
    * Telephone number of contact person at waypoint
    */
    // @ApiMember(Description="Telephone number of contact person at waypoint", IsRequired=true)
    public var contactNumber:String

    /**
    * Instructions for driver to follow at waypoint
    */
    // @ApiMember(Description="Instructions for driver to follow at waypoint", IsRequired=true)
    public var deliveryInstructions:String

    /**
    * Waypoint address
    */
    // @ApiMember(Description="Waypoint address", IsRequired=true)
    public var address:String

    required public init(){}
}

public enum ScheduleType : Int, Codable
{
    case NextAvailable = 0
    case SpecificTime = 1
}

public class RequestQuoteResponse : ApiServiceResponse
{
    /**
    * Is there an issue for the waypoints details specified?
    */
    // @ApiMember(Description="Is there an issue for the waypoints details specified?")
    public var waypointIssue:Bool

    /**
    * Is the quote created successfully and ready to be placed as an order?
    */
    // @ApiMember(Description="Is the quote created successfully and ready to be placed as an order?")
    public var quoteReady:Bool

    /**
    * Is the quote expired?
    */
    // @ApiMember(Description="Is the quote expired?")
    public var quoteExpired:Bool

    /**
    * The total distance for the quote
    */
    // @ApiMember(Description="The total distance for the quote")
    public var totalDistance:Double

    /**
    * The total distance for the quote, formatted as a string
    */
    // @ApiMember(Description="The total distance for the quote, formatted as a string")
    public var totalDistanceValue:String

    /**
    * The date and time the order is scheduled for in ISO 8601 string format, will be set if IsScheduled is true
    */
    // @ApiMember(Description="The date and time the order is scheduled for in ISO 8601 string format, will be set if IsScheduled is true")
    public var scheduledDate:String

    /**
    * The subtotal of the order before VAT
    */
    // @ApiMember(Description="The subtotal of the order before VAT")
    public var subTotal:String

    /**
    * The total of the order after VAT
    */
    // @ApiMember(Description="The total of the order after VAT")
    public var finalPrice:String

    /**
    * The amount of VAT 
    */
    // @ApiMember(Description="The amount of VAT ")
    public var vatValue:String

    /**
    * Will contain a message if there might be a problem with a scheduled quote
    */
    // @ApiMember(Description="Will contain a message if there might be a problem with a scheduled quote")
    public var schedulingNotice:String

    /**
    * Will contain a message if there is a problem with a scheduled quote, if the order is scheduled to soon to opening times
    */
    // @ApiMember(Description="Will contain a message if there is a problem with a scheduled quote, if the order is scheduled to soon to opening times")
    public var schedulingError:String

    /**
    * The ID of the generated quote, needed when you want to change this quote later
    */
    // @ApiMember(Description="The ID of the generated quote, needed when you want to change this quote later")
    public var quoteId:String

    /**
    * User friendly waybill number
    */
    // @ApiMember(Description="User friendly waybill number")
    public var wayBill:String

    /**
    * The date this order was created
    */
    // @ApiMember(Description="The date this order was created")
    public var dateCreated:String

    /**
    * The date this quote was last changed
    */
    // @ApiMember(Description="The date this quote was last changed")
    public var lastUpdated:String

    /**
    * List of quote information for pricing etc between each waypoint
    */
    // @ApiMember(Description="List of quote information for pricing etc between each waypoint")
    public var waypoints:[WaypointQuoteInformation] = []

    /**
    * List with validation information for each waypoint
    */
    // @ApiMember(Description="List with validation information for each waypoint")
    public var waypointValidations:[WaypointValidationInformation] = []

    required public init(){ super.init() }

    private enum CodingKeys : String, CodingKey {
        case waypointIssue
        case quoteReady
        case quoteExpired
        case totalDistance
        case totalDistanceValue
        case scheduledDate
        case subTotal
        case finalPrice
        case vatValue
        case schedulingNotice
        case schedulingError
        case quoteId
        case wayBill
        case dateCreated
        case lastUpdated
        case waypoints
        case waypointValidations
    }

    required public init(from decoder: Decoder) throws {
        try super.init(from: decoder)
        let container = try decoder.container(keyedBy: CodingKeys.self)
        waypointIssue = try container.decodeIfPresent(Bool.self, forKey: .waypointIssue)
        quoteReady = try container.decodeIfPresent(Bool.self, forKey: .quoteReady)
        quoteExpired = try container.decodeIfPresent(Bool.self, forKey: .quoteExpired)
        totalDistance = try container.decodeIfPresent(Double.self, forKey: .totalDistance)
        totalDistanceValue = try container.decodeIfPresent(String.self, forKey: .totalDistanceValue)
        scheduledDate = try container.decodeIfPresent(String.self, forKey: .scheduledDate)
        subTotal = try container.decodeIfPresent(String.self, forKey: .subTotal)
        finalPrice = try container.decodeIfPresent(String.self, forKey: .finalPrice)
        vatValue = try container.decodeIfPresent(String.self, forKey: .vatValue)
        schedulingNotice = try container.decodeIfPresent(String.self, forKey: .schedulingNotice)
        schedulingError = try container.decodeIfPresent(String.self, forKey: .schedulingError)
        quoteId = try container.decodeIfPresent(String.self, forKey: .quoteId)
        wayBill = try container.decodeIfPresent(String.self, forKey: .wayBill)
        dateCreated = try container.decodeIfPresent(String.self, forKey: .dateCreated)
        lastUpdated = try container.decodeIfPresent(String.self, forKey: .lastUpdated)
        waypoints = try container.decodeIfPresent([WaypointQuoteInformation].self, forKey: .waypoints) ?? []
        waypointValidations = try container.decodeIfPresent([WaypointValidationInformation].self, forKey: .waypointValidations) ?? []
    }

    public override func encode(to encoder: Encoder) throws {
        try super.encode(to: encoder)
        var container = encoder.container(keyedBy: CodingKeys.self)
        if waypointIssue != nil { try container.encode(waypointIssue, forKey: .waypointIssue) }
        if quoteReady != nil { try container.encode(quoteReady, forKey: .quoteReady) }
        if quoteExpired != nil { try container.encode(quoteExpired, forKey: .quoteExpired) }
        if totalDistance != nil { try container.encode(totalDistance, forKey: .totalDistance) }
        if totalDistanceValue != nil { try container.encode(totalDistanceValue, forKey: .totalDistanceValue) }
        if scheduledDate != nil { try container.encode(scheduledDate, forKey: .scheduledDate) }
        if subTotal != nil { try container.encode(subTotal, forKey: .subTotal) }
        if finalPrice != nil { try container.encode(finalPrice, forKey: .finalPrice) }
        if vatValue != nil { try container.encode(vatValue, forKey: .vatValue) }
        if schedulingNotice != nil { try container.encode(schedulingNotice, forKey: .schedulingNotice) }
        if schedulingError != nil { try container.encode(schedulingError, forKey: .schedulingError) }
        if quoteId != nil { try container.encode(quoteId, forKey: .quoteId) }
        if wayBill != nil { try container.encode(wayBill, forKey: .wayBill) }
        if dateCreated != nil { try container.encode(dateCreated, forKey: .dateCreated) }
        if lastUpdated != nil { try container.encode(lastUpdated, forKey: .lastUpdated) }
        if waypoints.count > 0 { try container.encode(waypoints, forKey: .waypoints) }
        if waypointValidations.count > 0 { try container.encode(waypointValidations, forKey: .waypointValidations) }
    }
}

public class ApiServiceResponse : IServiceResponse, Codable
{
    /**
    * Information about the response.
    */
    // @ApiMember(Description="Information about the response.", IsRequired=true)
    public var Description:String

    /**
    * Heading or summary of the response.
    */
    // @ApiMember(Description="Heading or summary of the response.", IsRequired=true)
    public var heading:String

    /**
    * Did the intended operation for this response complete successfully?
    */
    // @ApiMember(DataType="boolean", Description="Did the intended operation for this response complete successfully?", IsRequired=true)
    public var wasSuccessful:Bool

    required public init(){}
}

public class WaypointQuoteInformation : LinkedWaypoint
{
    /**
    * Distance between waypoints as a number
    */
    // @ApiMember(Description="Distance between waypoints as a number")
    public var distance:Double

    /**
    * String formatted distance
    */
    // @ApiMember(Description="String formatted distance")
    public var distanceValue:String

    public var waypointValid:Bool
    public var message:String
    public var errorDetails:[String] = []
    /**
    * Caculated price between waypoints excluding vat
    */
    // @ApiMember(Description="Caculated price between waypoints excluding vat")
    public var price:Double

    /**
    * Price excluding vat formatted as a string rand value
    */
    // @ApiMember(Description="Price excluding vat formatted as a string rand value")
    public var priceValue:String

    /**
    * The price between waypoints including vat
    */
    // @ApiMember(Description="The price between waypoints including vat")
    public var priceWithVAT:Double

    /**
    * The price including vat formatted as a rand value string
    */
    // @ApiMember(Description="The price including vat formatted as a rand value string")
    public var priceValueWithVAT:String

    required public init(){ super.init() }

    private enum CodingKeys : String, CodingKey {
        case distance
        case distanceValue
        case waypointValid
        case message
        case errorDetails
        case price
        case priceValue
        case priceWithVAT
        case priceValueWithVAT
    }

    required public init(from decoder: Decoder) throws {
        try super.init(from: decoder)
        let container = try decoder.container(keyedBy: CodingKeys.self)
        distance = try container.decodeIfPresent(Double.self, forKey: .distance)
        distanceValue = try container.decodeIfPresent(String.self, forKey: .distanceValue)
        waypointValid = try container.decodeIfPresent(Bool.self, forKey: .waypointValid)
        message = try container.decodeIfPresent(String.self, forKey: .message)
        errorDetails = try container.decodeIfPresent([String].self, forKey: .errorDetails) ?? []
        price = try container.decodeIfPresent(Double.self, forKey: .price)
        priceValue = try container.decodeIfPresent(String.self, forKey: .priceValue)
        priceWithVAT = try container.decodeIfPresent(Double.self, forKey: .priceWithVAT)
        priceValueWithVAT = try container.decodeIfPresent(String.self, forKey: .priceValueWithVAT)
    }

    public override func encode(to encoder: Encoder) throws {
        try super.encode(to: encoder)
        var container = encoder.container(keyedBy: CodingKeys.self)
        if distance != nil { try container.encode(distance, forKey: .distance) }
        if distanceValue != nil { try container.encode(distanceValue, forKey: .distanceValue) }
        if waypointValid != nil { try container.encode(waypointValid, forKey: .waypointValid) }
        if message != nil { try container.encode(message, forKey: .message) }
        if errorDetails.count > 0 { try container.encode(errorDetails, forKey: .errorDetails) }
        if price != nil { try container.encode(price, forKey: .price) }
        if priceValue != nil { try container.encode(priceValue, forKey: .priceValue) }
        if priceWithVAT != nil { try container.encode(priceWithVAT, forKey: .priceWithVAT) }
        if priceValueWithVAT != nil { try container.encode(priceValueWithVAT, forKey: .priceValueWithVAT) }
    }
}

public class LinkedWaypoint : Codable
{
    public var fromWaypointNumber:Int
    public var toWaypointNumber:Int
    public var fromLatitude:Double
    public var fromLongitude:Double
    public var toLatitude:Double
    public var toLongitude:Double

    required public init(){}
}

public class WaypointValidationInformation : Codable
{
    public var waypointNumber:Int
    public var isValid:Bool
    public var errorMessages:[String] = []

    required public init(){}
}


Swift RequestQuote DTOs

To override the Content-type in your clients, use the HTTP Accept Header, append the .csv suffix or ?format=csv

HTTP + CSV

The following are sample HTTP requests and responses. The placeholders shown need to be replaced with actual values.

POST /quote HTTP/1.1 
Host: api.1fetch.co.za 
Accept: text/csv
Content-Type: text/csv
Content-Length: length

{"Waypoints":[{"WaypointNumber":0,"Latitude":0,"Longitude":0,"ContactName":"String","ContactNumber":"String","DeliveryInstructions":"String","Address":"String"}],"IsScheduled":false,"ScheduleType":0,"ScheduledDate":"String","QuoteId":"00000000-0000-0000-0000-000000000000","Test":false,"ApiKey":"String"}
HTTP/1.1 200 OK
Content-Type: text/csv
Content-Length: length

{Unable to show example output for type 'RequestQuoteResponse' using the custom 'csv' filter}One or more errors occurred. (Object reference not set to an instance of an object.)