ClubReady Api

<back to all web services

SellContractAndSetupClientRequest

The following routes are available for this service:
POST/sales/contract/sold/new/userCreate a user and sell them a package Create a user and sell them a package. **New Operation** The PaymentMethods property is an array of objects describing how you want ClubReady to take payment while selling the PackageId/InstallmentPlanId. The deprecated fields (AcctToken, Last4, ExpMonth, ExpYear, AcctType, BnkRoute, and IsTemp) must be omitted or null. **Deprecated Operation** Provide the AcctToken, Last4, ExpMonth, ExpYear, AcctType, BnkRoute, and IsTemp used in the ClubReadyGateway API in order to create a Payment Profile to the user specified. PaymentMethods must be omitted or null.
import Foundation
import ServiceStack

// @ApiResponse(Description="", ResponseType=typeof(SellContractAndSetupClientResponse), StatusCode=200)
public class SellContractAndSetupClientRequest : SellContractAndSetupClientDto, IRestrictedApiRequest
{
    /**
    * Api Authentication Key
    */
    // @ApiMember(Description="Api Authentication Key", IsRequired=true, ParameterType="query")
    public var apiKey:String

    /**
    * Id for the chain of the Api Key
    */
    // @ApiMember(Description="Id for the chain of the Api Key", ParameterType="query")
    public var chainId:Int?

    /**
    * Id of the store for the user
    */
    // @ApiMember(Description="Id of the store for the user", IsRequired=true, ParameterType="query")
    public var storeId:Int?

    /**
    * Package Id being sold
    */
    // @ApiMember(Description="Package Id being sold", IsRequired=true)
    public var packageId:Int

    /**
    * Installment Plan Id being sold
    */
    // @ApiMember(Description="Installment Plan Id being sold", IsRequired=true)
    public var installmentPlanId:Int

    /**
    * Amount being paid
    */
    // @ApiMember(Description="Amount being paid", IsRequired=true)
    public var paymentAmount:Double

    /**
    * Date contract takes affect
    */
    // @ApiMember(Description="Date contract takes affect")
    public var startDate:Date?

    /**
    * First Name
    */
    // @ApiMember(Description="First Name", IsRequired=true)
    public var firstName:String

    /**
    * Last Name
    */
    // @ApiMember(Description="Last Name", IsRequired=true)
    public var lastName:String

    /**
    * Email Address
    */
    // @ApiMember(Description="Email Address", IsRequired=true)
    public var email:String

    /**
    * Gender
    */
    // @ApiMember(Description="Gender")
    public var gender:String

    /**
    * Address
    */
    // @ApiMember(Description="Address")
    public var address:String

    /**
    * City
    */
    // @ApiMember(Description="City")
    public var city:String

    /**
    * State
    */
    // @ApiMember(Description="State")
    public var state:String

    /**
    * Zip Code
    */
    // @ApiMember(Description="Zip Code")
    public var zip:String

    /**
    * Home phone
    */
    // @ApiMember(Description="Home phone")
    public var phone:String

    /**
    * Work phone
    */
    // @ApiMember(Description="Work phone")
    public var workPhone:String

    /**
    * Date of Birth
    */
    // @ApiMember(Description="Date of Birth")
    public var dateOfBirth:Date?

    /**
    * Cell phone
    */
    // @ApiMember(Description="Cell phone")
    public var cellPhone:String

    /**
    * Add an internal note for the new prospect
    */
    // @ApiMember(Description="Add an internal note for the new prospect")
    public var note:String

    /**
    * Unique Id for the user from your system. We store internally as ExternalUserId
    */
    // @ApiMember(Description="Unique Id for the user from your system. We store internally as ExternalUserId")
    public var externalId:String

    /**
    * Promo code to apply a discount.
    */
    // @ApiMember(Description="Promo code to apply a discount.")
    public var promoCode:String

    /**
    * Username should be between 4 and 255 characters long
    */
    // @ApiMember(Description="Username should be between 4 and 255 characters long")
    public var username:String

    /**
    * ReferralTypeId
    */
    // @ApiMember(Description="ReferralTypeId")
    public var referralTypeId:Int?

    /**
    * Emergency contact name
    */
    // @ApiMember(Description="Emergency contact name")
    public var emergencyContactName:String

    /**
    * Emergency contact phone number
    */
    // @ApiMember(Description="Emergency contact phone number")
    public var emergencyContactPhone:String

    /**
    * Emergency contact relationship
    */
    // @ApiMember(Description="Emergency contact relationship")
    public var emergencyContactType:String

    /**
    * An array of Payment Methods to be used for this purchase. Any entry with PreferredOnFile is assumed if omitted or null.  Each object of the array may contain properties:| Property | Description || --- | --- || PaymentMethodType | Usually "AcctToken" (Default or omitted/null) or "PreferredOnFile" || PaymentAmount | The amount to be attempted for this Payment Method. When omitted (or null), the Request's PaymentAmount will be attempted || AcctToken | The AcctToken to attempt payment (when using PaymentMethodType:AcctToken) || ProfileToken | When provided (with AcctToken), a Payment Profile will be created (this will prevent the requirement to call `/sales/paymentprofile/import` (when using PaymentMethodType:AcctToken) || DoNotUpdatePaymentTypePreference | When using ProfileToken, do not set the PaymentTypePreference (for more information, see `/sales/paymentprofile/import` (when using PaymentMethodType:AcctToken) || | |* Scenario #1: Use a Gift Card with PreferredOnFile to cover the amount not approved by the Gift Card.  JSON:```json{    PaymentMethods: [        {            "PaymentMethodType":"AcctToken",            "PaymentAmount":"1.00",            "AcctToken":"eyJ...GiftCard AcctToken...",            "ProfileToken":"eyJ...Gift Card ProfileToken..."        },        {            "PaymentMethodType":"PreferredOnFile",            "PaymentAmount":"1.00"        }    ]}```JSV:```[{PaymentMethodType:AcctToken,PaymentAmount:1.00,AcctToken:eyj...,ProfileToken:eyJ...},{PaymentMethodType:PreferredOnFile,PaymentAmount:1.00}]```* Scenario #2: Use a Gift Card with PreferredOnFile to cover the amount not approved by the Gift Card.  JSON:```json{    PaymentMethods: [        {            "PaymentMethodType":"AcctToken",            "PaymentAmount":"1.00",            "AcctToken":"eyJ...GiftCard AcctToken...",            "ProfileToken":"eyJ...Gift Card ProfileToken..."        },        {            "PaymentMethodType":"PreferredOnFile",            "PaymentAmount":"1.00"        }    ]}```JSV:```jsv[{PaymentMethodType:AcctToken,PaymentAmount:1.00,AcctToken:eyj...,ProfileToken:eyJ...},{PaymentMethodType:PreferredOnFile,PaymentAmount:1.00}]```Notes:  * The example shows PaymentAmount of 1.00 for both "AcctToken" and "PreferredOnFile". This is for the examplewith a total of $1.00. The firstPaymentMethod (the Gift Card) will be attempted for $1.00. If it partially approvesfor less than 1.00 (example: $0.80), the second payment method (PreferredOnFile) will be attempted for the lesser ofit's PaymentAmount and the remaining amount (example: $0.20).* Because this endpoint creates a new user, the "PreferredOnFile" option is not applicable. Also, ProfileToken withthe OwnerType "TempstUser" is required because the Payment Profile owner will be converted to the newly created user.* When using Query String (or this web site), this value must be encoded with JSV [(JSON-like Separated Values)](https://docs.servicestack.net/jsv-format).Basic steps to convert JSON to JSV: 1) Remove properties that are null, 2) Remove white space including line feeds, 3) Remove quotes.
    */
    // @ApiMember(Description="\r\nAn array of Payment Methods to be used for this purchase. Any entry with PreferredOnFile is assumed if omitted or null.  \r\n\r\nEach object of the array may contain properties:\r\n\r\n| Property | Description |\r\n| --- | --- |\r\n| PaymentMethodType | Usually \"AcctToken\" (Default or omitted/null) or \"PreferredOnFile\" |\r\n| PaymentAmount | The amount to be attempted for this Payment Method. When omitted (or null), the Request's PaymentAmount will be attempted |\r\n| AcctToken | The AcctToken to attempt payment (when using PaymentMethodType:AcctToken) |\r\n| ProfileToken | When provided (with AcctToken), a Payment Profile will be created (this will prevent the requirement to call `/sales/paymentprofile/import` (when using PaymentMethodType:AcctToken) |\r\n| DoNotUpdatePaymentTypePreference | When using ProfileToken, do not set the PaymentTypePreference (for more information, see `/sales/paymentprofile/import` (when using PaymentMethodType:AcctToken) |\r\n| | |\r\n\r\n* Scenario #1: Use a Gift Card with PreferredOnFile to cover the amount not approved by the Gift Card.  \r\n\r\nJSON:\r\n```json\r\n{\r\n    PaymentMethods: [\r\n        {\r\n            \"PaymentMethodType\":\"AcctToken\",\r\n            \"PaymentAmount\":\"1.00\",\r\n            \"AcctToken\":\"eyJ...GiftCard AcctToken...\",\r\n            \"ProfileToken\":\"eyJ...Gift Card ProfileToken...\"\r\n        },\r\n        {\r\n            \"PaymentMethodType\":\"PreferredOnFile\",\r\n            \"PaymentAmount\":\"1.00\"\r\n        }\r\n    ]\r\n}\r\n```\r\nJSV:\r\n```\r\n[{PaymentMethodType:AcctToken,PaymentAmount:1.00,AcctToken:eyj...,ProfileToken:eyJ...},{PaymentMethodType:PreferredOnFile,PaymentAmount:1.00}]\r\n```\r\n\r\n* Scenario #2: Use a Gift Card with PreferredOnFile to cover the amount not approved by the Gift Card.  \r\n\r\nJSON:\r\n```json\r\n{\r\n    PaymentMethods: [\r\n        {\r\n            \"PaymentMethodType\":\"AcctToken\",\r\n            \"PaymentAmount\":\"1.00\",\r\n            \"AcctToken\":\"eyJ...GiftCard AcctToken...\",\r\n            \"ProfileToken\":\"eyJ...Gift Card ProfileToken...\"\r\n        },\r\n        {\r\n            \"PaymentMethodType\":\"PreferredOnFile\",\r\n            \"PaymentAmount\":\"1.00\"\r\n        }\r\n    ]\r\n}\r\n```\r\nJSV:\r\n```jsv\r\n[{PaymentMethodType:AcctToken,PaymentAmount:1.00,AcctToken:eyj...,ProfileToken:eyJ...},{PaymentMethodType:PreferredOnFile,PaymentAmount:1.00}]\r\n```\r\n\r\nNotes:  \r\n\r\n* The example shows PaymentAmount of 1.00 for both \"AcctToken\" and \"PreferredOnFile\". This is for the example\r\nwith a total of $1.00. The firstPaymentMethod (the Gift Card) will be attempted for $1.00. If it partially approves\r\nfor less than 1.00 (example: $0.80), the second payment method (PreferredOnFile) will be attempted for the lesser of\r\nit's PaymentAmount and the remaining amount (example: $0.20).\r\n\r\n* Because this endpoint creates a new user, the \"PreferredOnFile\" option is not applicable. Also, ProfileToken with\r\nthe OwnerType \"TempstUser\" is required because the Payment Profile owner will be converted to the newly created user.\r\n\r\n* When using Query String (or this web site), this value must be encoded with JSV [(JSON-like Separated Values)](https://docs.servicestack.net/jsv-format).\r\nBasic steps to convert JSON to JSV: 1) Remove properties that are null, 2) Remove white space including line feeds, 3) Remove quotes.\r\n")
    public var paymentMethods:[PaymentMethodDto] = []

    public var restrictedId:Int?
    public var restrictedResourceType:RestrictedResourceType
    /**
    * **Deprecated** (Use `PaymentMethods` with `ProfileToken`)  AcctToken provided by creating a Payment Profile with the Vault Api. Required if Package requires purchase and PaymentMethods is empty.
    */
    // @ApiMember(Description="\r\n**Deprecated** (Use `PaymentMethods` with `ProfileToken`)  \r\n\r\nAcctToken provided by creating a Payment Profile with the Vault Api. Required if Package requires purchase and PaymentMethods is empty.")
    public var acctToken:String

    /**
    * **Deprecated** (Use `PaymentMethods` with `ProfileToken`)  Last 4 digits of the Payment Profile. Required with AcctToken.
    */
    // @ApiMember(Description="\r\n**Deprecated** (Use `PaymentMethods` with `ProfileToken`)  \r\n\r\nLast 4 digits of the Payment Profile. Required with AcctToken.")
    public var last4:String

    /**
    * **Deprecated** (Use `PaymentMethods` with `ProfileToken`)  2 digit expiration month. **Required with AcctToken for Credit Card.**
    */
    // @ApiMember(Description="\r\n**Deprecated** (Use `PaymentMethods` with `ProfileToken`)  \r\n\r\n2 digit expiration month. **Required with AcctToken for Credit Card.**")
    public var expMonth:Int?

    /**
    * **Deprecated** (Use `PaymentMethods` with `ProfileToken`)  2 digit expiration year. **Required with AcctToken for Credit Card.**
    */
    // @ApiMember(Description="\r\n**Deprecated** (Use `PaymentMethods` with `ProfileToken`)  \r\n\r\n2 digit expiration year. **Required with AcctToken for Credit Card.**")
    public var expYear:Int?

    /**
    * **Deprecated** (Use `PaymentMethods` with `ProfileToken`)  The Account Type the Payment Profile<details><summary>Common Values</summary><table>    <thead>        <tr><th>Text</th><th>Numerical</th><th>Account Type</th></tr>    </thead>    <tbody>        <tr><td>VISA</td><td>1</td><td>Visa</td></tr>        <tr><td>MC</td><td>2</td><td>MasterCard</td></tr>        <tr><td>Disc</td><td>3</td><td>Discover</td></tr>        <tr><td>Amex</td><td>4</td><td>American Express</td></tr>        <tr><td>PC</td><td>11</td><td>Personal Checking</td></tr>        <tr><td>PS</td><td>12</td><td>Personal Savings</td></tr>        <tr><td>BC</td><td>13</td><td>Business Checking</td></tr>    </tbody></table><p>You may use the Text or the Numerical value.</p></details>
    */
    // @ApiMember(Description="\r\n**Deprecated** (Use `PaymentMethods` with `ProfileToken`)  \r\n\r\nThe Account Type the Payment Profile\r\n\r\n<details>\r\n<summary>Common Values</summary>\r\n<table>\r\n    <thead>\r\n        <tr><th>Text</th><th>Numerical</th><th>Account Type</th></tr>\r\n    </thead>\r\n    <tbody>\r\n        <tr><td>VISA</td><td>1</td><td>Visa</td></tr>\r\n        <tr><td>MC</td><td>2</td><td>MasterCard</td></tr>\r\n        <tr><td>Disc</td><td>3</td><td>Discover</td></tr>\r\n        <tr><td>Amex</td><td>4</td><td>American Express</td></tr>\r\n        <tr><td>PC</td><td>11</td><td>Personal Checking</td></tr>\r\n        <tr><td>PS</td><td>12</td><td>Personal Savings</td></tr>\r\n        <tr><td>BC</td><td>13</td><td>Business Checking</td></tr>\r\n    </tbody>\r\n</table>\r\n<p>You may use the Text or the Numerical value.</p>\r\n</details>")
    public var acctType:AcctType?

    /**
    * **Deprecated** (Use `PaymentMethods` with `ProfileToken`)  Bank Routing Number. **Required with AcctToken for Bank Accounts.**
    */
    // @ApiMember(Description="\r\n**Deprecated** (Use `PaymentMethods` with `ProfileToken`)  \r\n\r\nBank Routing Number. **Required with AcctToken for Bank Accounts.**")
    public var bnkRoute:Int?

    /**
    * **Deprecated** (Use `PaymentMethods` with `ProfileToken`)  Whether the Payment Profile is Temporary. (One time transactions and Gift Cards are IsTemp = True).
    */
    // @ApiMember(Description="\r\n**Deprecated** (Use `PaymentMethods` with `ProfileToken`)  \r\n\r\nWhether the Payment Profile is Temporary. (One time transactions and Gift Cards are IsTemp = True).")
    public var isTemp:Bool

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

    private enum CodingKeys : String, CodingKey {
        case apiKey
        case chainId
        case storeId
        case packageId
        case installmentPlanId
        case paymentAmount
        case startDate
        case firstName
        case lastName
        case email
        case gender
        case address
        case city
        case state
        case zip
        case phone
        case workPhone
        case dateOfBirth
        case cellPhone
        case note
        case externalId
        case promoCode
        case username
        case referralTypeId
        case emergencyContactName
        case emergencyContactPhone
        case emergencyContactType
        case paymentMethods
        case restrictedId
        case restrictedResourceType
        case acctToken
        case last4
        case expMonth
        case expYear
        case acctType
        case bnkRoute
        case isTemp
    }

    required public init(from decoder: Decoder) throws {
        try super.init(from: decoder)
        let container = try decoder.container(keyedBy: CodingKeys.self)
        apiKey = try container.decodeIfPresent(String.self, forKey: .apiKey)
        chainId = try container.decodeIfPresent(Int.self, forKey: .chainId)
        storeId = try container.decodeIfPresent(Int.self, forKey: .storeId)
        packageId = try container.decodeIfPresent(Int.self, forKey: .packageId)
        installmentPlanId = try container.decodeIfPresent(Int.self, forKey: .installmentPlanId)
        paymentAmount = try container.decodeIfPresent(Double.self, forKey: .paymentAmount)
        startDate = try container.decodeIfPresent(Date.self, forKey: .startDate)
        firstName = try container.decodeIfPresent(String.self, forKey: .firstName)
        lastName = try container.decodeIfPresent(String.self, forKey: .lastName)
        email = try container.decodeIfPresent(String.self, forKey: .email)
        gender = try container.decodeIfPresent(String.self, forKey: .gender)
        address = try container.decodeIfPresent(String.self, forKey: .address)
        city = try container.decodeIfPresent(String.self, forKey: .city)
        state = try container.decodeIfPresent(String.self, forKey: .state)
        zip = try container.decodeIfPresent(String.self, forKey: .zip)
        phone = try container.decodeIfPresent(String.self, forKey: .phone)
        workPhone = try container.decodeIfPresent(String.self, forKey: .workPhone)
        dateOfBirth = try container.decodeIfPresent(Date.self, forKey: .dateOfBirth)
        cellPhone = try container.decodeIfPresent(String.self, forKey: .cellPhone)
        note = try container.decodeIfPresent(String.self, forKey: .note)
        externalId = try container.decodeIfPresent(String.self, forKey: .externalId)
        promoCode = try container.decodeIfPresent(String.self, forKey: .promoCode)
        username = try container.decodeIfPresent(String.self, forKey: .username)
        referralTypeId = try container.decodeIfPresent(Int.self, forKey: .referralTypeId)
        emergencyContactName = try container.decodeIfPresent(String.self, forKey: .emergencyContactName)
        emergencyContactPhone = try container.decodeIfPresent(String.self, forKey: .emergencyContactPhone)
        emergencyContactType = try container.decodeIfPresent(String.self, forKey: .emergencyContactType)
        paymentMethods = try container.decodeIfPresent([PaymentMethodDto].self, forKey: .paymentMethods) ?? []
        restrictedId = try container.decodeIfPresent(Int.self, forKey: .restrictedId)
        restrictedResourceType = try container.decodeIfPresent(RestrictedResourceType.self, forKey: .restrictedResourceType)
        acctToken = try container.decodeIfPresent(String.self, forKey: .acctToken)
        last4 = try container.decodeIfPresent(String.self, forKey: .last4)
        expMonth = try container.decodeIfPresent(Int.self, forKey: .expMonth)
        expYear = try container.decodeIfPresent(Int.self, forKey: .expYear)
        acctType = try container.decodeIfPresent(AcctType.self, forKey: .acctType)
        bnkRoute = try container.decodeIfPresent(Int.self, forKey: .bnkRoute)
        isTemp = try container.decodeIfPresent(Bool.self, forKey: .isTemp)
    }

    public override func encode(to encoder: Encoder) throws {
        try super.encode(to: encoder)
        var container = encoder.container(keyedBy: CodingKeys.self)
        if apiKey != nil { try container.encode(apiKey, forKey: .apiKey) }
        if chainId != nil { try container.encode(chainId, forKey: .chainId) }
        if storeId != nil { try container.encode(storeId, forKey: .storeId) }
        if packageId != nil { try container.encode(packageId, forKey: .packageId) }
        if installmentPlanId != nil { try container.encode(installmentPlanId, forKey: .installmentPlanId) }
        if paymentAmount != nil { try container.encode(paymentAmount, forKey: .paymentAmount) }
        if startDate != nil { try container.encode(startDate, forKey: .startDate) }
        if firstName != nil { try container.encode(firstName, forKey: .firstName) }
        if lastName != nil { try container.encode(lastName, forKey: .lastName) }
        if email != nil { try container.encode(email, forKey: .email) }
        if gender != nil { try container.encode(gender, forKey: .gender) }
        if address != nil { try container.encode(address, forKey: .address) }
        if city != nil { try container.encode(city, forKey: .city) }
        if state != nil { try container.encode(state, forKey: .state) }
        if zip != nil { try container.encode(zip, forKey: .zip) }
        if phone != nil { try container.encode(phone, forKey: .phone) }
        if workPhone != nil { try container.encode(workPhone, forKey: .workPhone) }
        if dateOfBirth != nil { try container.encode(dateOfBirth, forKey: .dateOfBirth) }
        if cellPhone != nil { try container.encode(cellPhone, forKey: .cellPhone) }
        if note != nil { try container.encode(note, forKey: .note) }
        if externalId != nil { try container.encode(externalId, forKey: .externalId) }
        if promoCode != nil { try container.encode(promoCode, forKey: .promoCode) }
        if username != nil { try container.encode(username, forKey: .username) }
        if referralTypeId != nil { try container.encode(referralTypeId, forKey: .referralTypeId) }
        if emergencyContactName != nil { try container.encode(emergencyContactName, forKey: .emergencyContactName) }
        if emergencyContactPhone != nil { try container.encode(emergencyContactPhone, forKey: .emergencyContactPhone) }
        if emergencyContactType != nil { try container.encode(emergencyContactType, forKey: .emergencyContactType) }
        if paymentMethods.count > 0 { try container.encode(paymentMethods, forKey: .paymentMethods) }
        if restrictedId != nil { try container.encode(restrictedId, forKey: .restrictedId) }
        if restrictedResourceType != nil { try container.encode(restrictedResourceType, forKey: .restrictedResourceType) }
        if acctToken != nil { try container.encode(acctToken, forKey: .acctToken) }
        if last4 != nil { try container.encode(last4, forKey: .last4) }
        if expMonth != nil { try container.encode(expMonth, forKey: .expMonth) }
        if expYear != nil { try container.encode(expYear, forKey: .expYear) }
        if acctType != nil { try container.encode(acctType, forKey: .acctType) }
        if bnkRoute != nil { try container.encode(bnkRoute, forKey: .bnkRoute) }
        if isTemp != nil { try container.encode(isTemp, forKey: .isTemp) }
    }
}

public class SellContractAndSetupClientDto : ApiDtoBase
{
    public var acctToken:String
    public var last4:String
    public var expMonth:Int?
    public var expYear:Int?
    public var acctType:AcctType?
    public var bnkRoute:Int?
    public var isTemp:Bool
    public var packageId:Int
    public var installmentPlanId:Int
    public var paymentAmount:Double
    public var startDate:Date?
    public var firstName:String
    public var lastName:String
    public var address:String
    public var city:String
    public var state:String
    public var zip:String
    public var email:String
    public var gender:String
    public var phone:String
    public var workPhone:String
    public var dateOfBirth:Date?
    public var cellPhone:String
    public var note:String
    public var externalId:String
    public var promoCode:String
    public var username:String
    public var referralTypeId:Int?
    public var emergencyContactName:String
    public var emergencyContactPhone:String
    public var emergencyContactType:String
    public var paymentMethods:[PaymentMethodDto] = []

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

    private enum CodingKeys : String, CodingKey {
        case acctToken
        case last4
        case expMonth
        case expYear
        case acctType
        case bnkRoute
        case isTemp
        case packageId
        case installmentPlanId
        case paymentAmount
        case startDate
        case firstName
        case lastName
        case address
        case city
        case state
        case zip
        case email
        case gender
        case phone
        case workPhone
        case dateOfBirth
        case cellPhone
        case note
        case externalId
        case promoCode
        case username
        case referralTypeId
        case emergencyContactName
        case emergencyContactPhone
        case emergencyContactType
        case paymentMethods
    }

    required public init(from decoder: Decoder) throws {
        try super.init(from: decoder)
        let container = try decoder.container(keyedBy: CodingKeys.self)
        acctToken = try container.decodeIfPresent(String.self, forKey: .acctToken)
        last4 = try container.decodeIfPresent(String.self, forKey: .last4)
        expMonth = try container.decodeIfPresent(Int.self, forKey: .expMonth)
        expYear = try container.decodeIfPresent(Int.self, forKey: .expYear)
        acctType = try container.decodeIfPresent(AcctType.self, forKey: .acctType)
        bnkRoute = try container.decodeIfPresent(Int.self, forKey: .bnkRoute)
        isTemp = try container.decodeIfPresent(Bool.self, forKey: .isTemp)
        packageId = try container.decodeIfPresent(Int.self, forKey: .packageId)
        installmentPlanId = try container.decodeIfPresent(Int.self, forKey: .installmentPlanId)
        paymentAmount = try container.decodeIfPresent(Double.self, forKey: .paymentAmount)
        startDate = try container.decodeIfPresent(Date.self, forKey: .startDate)
        firstName = try container.decodeIfPresent(String.self, forKey: .firstName)
        lastName = try container.decodeIfPresent(String.self, forKey: .lastName)
        address = try container.decodeIfPresent(String.self, forKey: .address)
        city = try container.decodeIfPresent(String.self, forKey: .city)
        state = try container.decodeIfPresent(String.self, forKey: .state)
        zip = try container.decodeIfPresent(String.self, forKey: .zip)
        email = try container.decodeIfPresent(String.self, forKey: .email)
        gender = try container.decodeIfPresent(String.self, forKey: .gender)
        phone = try container.decodeIfPresent(String.self, forKey: .phone)
        workPhone = try container.decodeIfPresent(String.self, forKey: .workPhone)
        dateOfBirth = try container.decodeIfPresent(Date.self, forKey: .dateOfBirth)
        cellPhone = try container.decodeIfPresent(String.self, forKey: .cellPhone)
        note = try container.decodeIfPresent(String.self, forKey: .note)
        externalId = try container.decodeIfPresent(String.self, forKey: .externalId)
        promoCode = try container.decodeIfPresent(String.self, forKey: .promoCode)
        username = try container.decodeIfPresent(String.self, forKey: .username)
        referralTypeId = try container.decodeIfPresent(Int.self, forKey: .referralTypeId)
        emergencyContactName = try container.decodeIfPresent(String.self, forKey: .emergencyContactName)
        emergencyContactPhone = try container.decodeIfPresent(String.self, forKey: .emergencyContactPhone)
        emergencyContactType = try container.decodeIfPresent(String.self, forKey: .emergencyContactType)
        paymentMethods = try container.decodeIfPresent([PaymentMethodDto].self, forKey: .paymentMethods) ?? []
    }

    public override func encode(to encoder: Encoder) throws {
        try super.encode(to: encoder)
        var container = encoder.container(keyedBy: CodingKeys.self)
        if acctToken != nil { try container.encode(acctToken, forKey: .acctToken) }
        if last4 != nil { try container.encode(last4, forKey: .last4) }
        if expMonth != nil { try container.encode(expMonth, forKey: .expMonth) }
        if expYear != nil { try container.encode(expYear, forKey: .expYear) }
        if acctType != nil { try container.encode(acctType, forKey: .acctType) }
        if bnkRoute != nil { try container.encode(bnkRoute, forKey: .bnkRoute) }
        if isTemp != nil { try container.encode(isTemp, forKey: .isTemp) }
        if packageId != nil { try container.encode(packageId, forKey: .packageId) }
        if installmentPlanId != nil { try container.encode(installmentPlanId, forKey: .installmentPlanId) }
        if paymentAmount != nil { try container.encode(paymentAmount, forKey: .paymentAmount) }
        if startDate != nil { try container.encode(startDate, forKey: .startDate) }
        if firstName != nil { try container.encode(firstName, forKey: .firstName) }
        if lastName != nil { try container.encode(lastName, forKey: .lastName) }
        if address != nil { try container.encode(address, forKey: .address) }
        if city != nil { try container.encode(city, forKey: .city) }
        if state != nil { try container.encode(state, forKey: .state) }
        if zip != nil { try container.encode(zip, forKey: .zip) }
        if email != nil { try container.encode(email, forKey: .email) }
        if gender != nil { try container.encode(gender, forKey: .gender) }
        if phone != nil { try container.encode(phone, forKey: .phone) }
        if workPhone != nil { try container.encode(workPhone, forKey: .workPhone) }
        if dateOfBirth != nil { try container.encode(dateOfBirth, forKey: .dateOfBirth) }
        if cellPhone != nil { try container.encode(cellPhone, forKey: .cellPhone) }
        if note != nil { try container.encode(note, forKey: .note) }
        if externalId != nil { try container.encode(externalId, forKey: .externalId) }
        if promoCode != nil { try container.encode(promoCode, forKey: .promoCode) }
        if username != nil { try container.encode(username, forKey: .username) }
        if referralTypeId != nil { try container.encode(referralTypeId, forKey: .referralTypeId) }
        if emergencyContactName != nil { try container.encode(emergencyContactName, forKey: .emergencyContactName) }
        if emergencyContactPhone != nil { try container.encode(emergencyContactPhone, forKey: .emergencyContactPhone) }
        if emergencyContactType != nil { try container.encode(emergencyContactType, forKey: .emergencyContactType) }
        if paymentMethods.count > 0 { try container.encode(paymentMethods, forKey: .paymentMethods) }
    }
}

public class ApiDtoBase : Codable
{
    public var apiKey:String
    public var storeId:Int?
    public var chainId:Int?

    required public init(){}
}

// @DataContract
public enum AcctType : Int, Codable
{
    case Uninitialized = 0
    case Visa = 1
    case MC = 2
    case Disc = 3
    case Amex = 4
    case Diners = 5
    case JCB = 6
    case enRoute = 7
    case PayPal = 8
    case BillMe = 9
    case PC = 11
    case PS = 12
    case BC = 13
    case BS = 14
    case Becs = 15
    case Bacs = 16
    case Maestro = 20
    case Solo = 21
    case VisaElectron = 22
    case CIBC = 23
    case RoyalBankCa = 24
    case TDCaTrust = 25
    case Scotia = 26
    case BMO = 27
    case HSBCCa = 28
    case UnionPay = 29
    case InterPayment = 30
    case Laser = 31
    case UnknownCredit = 40
    case TransArmor = 41
    case Factor4 = 42
    case XPass = 43
    case ConnectedAccount = 44
    case UnknownBank = 45
    case Error = -1
}

// @DataContract
public class PaymentMethodDto : Codable
{
    // @DataMember
    public var acctToken:String

    // @DataMember
    public var profileToken:String

    // @DataMember
    public var paymentProfileId:String

    // @DataMember
    public var paymentAmount:Double?

    // @DataMember
    public var paymentMethodType:PaymentMethodType?

    // @DataMember
    public var doNotUpdatePaymentTypePreference:Bool?

    required public init(){}
}

public enum PaymentMethodType : Int, Codable
{
    case Uninitialized = 0
    case PaymentProfileId = 1
    case PreferredOnFile = 2
    case AcctToken = 3
    case Error = -1
}

public enum RestrictedResourceType : String, Codable
{
    case Store
    case Chain
    case User
    case Undefined
}


Swift SellContractAndSetupClientRequest DTOs

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

HTTP + JSV

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

POST /sales/contract/sold/new/user HTTP/1.1 
Host: clubready.com 
Accept: text/jsv
Content-Type: text/jsv
Content-Length: length

{
	ApiKey: String,
	ChainId: 0,
	StoreId: 0,
	PackageId: 0,
	InstallmentPlanId: 0,
	PaymentAmount: 0,
	StartDate: 0001-01-01,
	FirstName: String,
	LastName: String,
	Email: String,
	Gender: String,
	Address: String,
	City: String,
	State: String,
	Zip: String,
	Phone: String,
	WorkPhone: String,
	DateOfBirth: 0001-01-01,
	CellPhone: String,
	Note: String,
	ExternalId: String,
	PromoCode: String,
	Username: String,
	ReferralTypeId: 0,
	EmergencyContactName: String,
	EmergencyContactPhone: String,
	EmergencyContactType: String,
	PaymentMethods: 
	[
		{
			AcctToken: String,
			ProfileToken: String,
			PaymentProfileId: String,
			PaymentAmount: 0,
			PaymentMethodType: Uninitialized,
			DoNotUpdatePaymentTypePreference: False
		}
	],
	RestrictedId: 0,
	RestrictedResourceType: Chain,
	AuthToken: String,
	AcctToken: String,
	Last4: String,
	ExpMonth: 0,
	ExpYear: 0,
	AcctType: Uninitialized,
	CardType: 0,
	BnkRoute: 0,
	IsTemp: False
}
HTTP/1.1 200 OK
Content-Type: text/jsv
Content-Length: length

{
	
}