Lease Approval & Checkout (Ecomm)

At this point your customer has been approved for an e-comm lease. This page walks through the remaining steps to finish out a lease application. To complete the steps on this page, you should still have the Koalafi orderId for the app in progress as well as the lease applicationId returned from the apply mutation.

1. Update Order Items

If a customer has had the chance to update their cart since their initial lease approval you need to call updateOrderItems before checkout to sync the Koalafi cart with the customer’s. Please note it is not necessary to call updateOrderItems after every cart change as we only need the final cart they have at checkout. For example, our e-commerce plugins call updateOrderItems before they open our modal on the checkout page. This ensures that the customer's cart and the Koalafi cart are always in sync.

An example of mutation for updateOrderItems looks something like:

mutation updateOrderItems($input: UpdateOrderItemsInput! ) {
  updateOrderItems(input: $input) {
    order {
      id
      details{
        items{
          price
        }
      }
    }
    orderErrors{
      __typename
      ... on CartValidation {
        message
        extensions {
          validationErrType
          approvalType
          approvedAmount
        }
      }
      ... on BadRequest{
        message
      }
      ... on CartMinNotMet{
        message
      }
    }  
  } 
}

For this response, the most important thing to check is orderErrors as any error needs to be addressed before the customer can continue with their application. We have broken down the different possible errors for this mutation and recommended resolution in our Handling Common Errors page.

Discount Codes / Coupons

Some retailers will offer discount codes or coupons at checkout. In order to make sure the Koalafi contract amount matches the discounted price from the merchant, you will need to apply the coupon/discount to the items' prices before calling updateOrderItems. Before calling this mutation, you need to make sure that the cart total you are sending matches the discounted cart total on the site and that each item's price is formatted to have 2 decimal places and greater than $0.00. If their cart contains multiple items, the price you send for each item should match what's shown on the e-comm site.

Non Leasable Items

Specifying whether a product is leasable is required when offering a lease-to-own financing option with Koalafi. Non-leasable products generally include weapons and non-physical goods such as gift cards, service fees, warranties or installation fees. It is important that Koalafi knows when a customer is purchasing a non-leaseable item as they can only make up a 20% of a customer's total purchase.

You can use the boolean field isLeaseable on the updateOrderItems input to indicate that an item is non-leaseable. By default, we assume all products are leaseable so this isLeaseable: false must be sent to let our system know otherwise.

Our e-commerce platform integrations allow merchants to tag all non-leaseable items in their inventory as such so that it's easy to send to Koalafi when a customer selects that item. We suggest a similar solution to all our direct API integration partners.

2. Update Order Address

If the customer's shipping address was not included in the initial application, add their shipping address to their Koalafi application using updateOrderAddress. You will need to pass both shippingAddress and billingAddress in the input. If you do not have the ability to collect a customer's shipping address then you can pass their billing address as their shipping address.

The following is an example input:

{
  "input": {
    "orderId": "< your orderID> ",
    "billingAddress": {
      "line1": "1800 Dingus Way",
      "city": "Powhatan",
      "state": "VA",
      "zip": "23138"
    },
    "shippingAddress": {
      "line1": "861 UPS Way",
      "city": "Powhatan",
      "state": "VA",
      "zip": "23138"
    }
  }
}

updateOrderAddress returns the updateOrderAddressResponse object which is made up of order and updateOrderErrors. For this use case you can ignore order and only need to check for a few updateOrderError types. A good example for this mutation looks like:

mutation UpdateAddress($input: UpdateOrderAddressInput!) {
  updateOrderAddress(input: $input){
    orderErrors{
      __typename
      ... on FatalError{
        message
      }
      ... on BadRequest{
        message
      }
      ... on NotFound{
        message
      }
    }
  }
}


If a FatalError is returned when there is an error within Koalafi or one of our downstream dependencies. If you get a FatalError you can retry the mutation without making changes. If the mutation fails again, show a message to the customer asking them to try again at a later time.

If a BadRequest or NotFound error is returned, you'll need to adjust the input and retry the mutation.

3. Update Employment

Next, we will need some additional information about the customer's employment. The customer will need to provide information about their pay frequency, last pay date, and next pay date which should be sent to Koalafi using updateEmployment mutation.

The input for this mutation will look like:

{
   "input":{
      "applicationId": 27645,
      "paymentFrequency": "monthly",
      "lastPayDate": "2022-09-09", 
     	"nextPayDate": "2022-10-09"
   }
}

updateEmployment is a small mutation that returns updateEmploymentResponse object which only contains updateEmploymentErrors.

An example mutation looks like:

mutation updateEmployment($input: UpdateEmploymentInput!) {
    updateEmployment(input: $input) {
      updateEmploymentErrors {
        __typename
        ... on FatalError {
          message
        }
        ... on BusinessError {
          message
        }
      }
    }
  }

A FatalError is returned when there is an error within Koalafi or one of our downstream dependencies. If you get a FatalError you can retry the mutation without making changes. If the mutation fails again, show a message to the customer asking them to try again at a later time.

A BusinessError occurs when there is an issue with the dates or frequency in the input. To prevent these errors, we recommend adding validation making sure that lastPayDate is a date within the last year and not a future date. For example, if today is January 10th, 2023 then they could enter a pay date between January 11th, 2022 and January 10th, 2023. If a BusinessError is returned, allow the customer the chance to adjust their employment information and then retry the mutation.

4. Update Bank Account

This is an optional step. You can add the customer's banking information with the following mutation. Both accountNumber and routingNumber must be present in the input.

The following is an example input:

{
  "input": {
    "applicationId": 26065,
    "bankAccount" :{
    	"accountNumber": "0987654321",
      "routingNumber": "123456789"
    }
  }
}

updateBankAccount returns no response other than the errors list. A good example for this mutation looks like:

mutation updateBankAccount($input: UpdateBankAccountInput!) {
  updateBankAccount(input: $input){
    updateBankAccountErrors{
      __typename
      ... on FatalError{
        message
      }
      ... on BadRequest{
        message
      }
      ... on SoftDecline{
        message
        extensions {
          displayText
        }
      }
      ... on HardDecline{
        message
      }
    }
  }
}

Most of the time when you encounter an error, you will need to have the customer review their bank account data and then retry the mutation. Our Handling Common Errors page explains what the different error type represents as well as the specific messaging and steps to take to resolve the errors. Theses errors must be resolved before moving on to Step 5.

5. Update Debit Info

The lease approval returned from apply is actually considered a pre-approval and in order to continue on with Koalafi financing, we need to run an authorization for an initial payment on their debit card. We will only charge the card after the customer has signed the lease agreement; if they choose not to sign the lease, the authorization will be removed.

We do not store the card details that were sent to us on apply so we will need the debitDetails to be resent along with the lease applicationId returned from apply, in an input that looks like:

{
   "input":{
      "debitDetails":{
         "cardholderFirstName":"Wally",
         "cardholderLastName":"Koala",
         "cardNumber":"4000056655665556",
         "expirationDate":"2023-05"
      },
      "applicationId": 25125
   }
}

The UpdateDebitInfoResponse object only returns updateDebitInfo errors so the mutation you send will be short but should listen for information on all possible errors.

mutation updateDebitInfo($input: UpdateDebitInfoInput!) {
  updateDebitInfo(input: $input) {
    updateDebitInfoErrors {
      __typename
      ... on FatalError {
        message
      }
      ... on HardDecline {
        message
      }
      ... on SoftDecline {
        message
        extensions {
          displayText
        }
      }
    }
  }
}

Most of the time when you encounter an error, you will need to have the customer review their debit data and then retry the mutation. Our Handling Common Errors page explains what the different error type represents as well as the specific messaging and steps to take to resolve the errors. Theses errors must be resolved before moving on to Step 6.

6. Generate Lease Contract

Once we successfully confirm the employment, shipping address and debit card provided by the customer, you will be able to generate payment terms and the lease document with generateLeaseContract mutation.

mutation GenerateContract($input: GenerateContractInput!) {
  generateLeaseContract(input: $input){
      details {
        welcomeLetter
        leaseAgreement
        summary {
          leaseTerm
          leaseAmount
          cashPlusPrice
          cashPlusTerm
          initialPaymentAmount
          paymentFrequency
          totalCostOfOwnership
          scheduledPaymentAmounts
        }
      }
      generateContractErrors {
        __typename
        ... on FatalError {
          message
          path
        }
        ... on BadRequest {
          message
          path
        }
      }
    }
}

If you encounter errors on this mutation, they will need to be resolved before moving forward. This mutation only works for leases so if you get a BadRequest error returned, double check that the orderId you have passed is for a lease, not a loan. If you get a FatalError back, then you should retry the mutation as this is caused by an internal or downstream error while trying to complete the mutation.

Once generateLeaseContract has successfully completed, you will need to show the returned documents to the customer to review and sign in order to complete their financing with Koalafi.

7. Sign Lease Agreement

After the customer has reviewed all payment and lease terms and has consented to entering the lease agreement, capture their consent using signLeaseAgreement.

The input for signLeaseAgreement looks like:

 {"input": { 
        "applicationId": "25125",
        "isSigned": true
    }
 }

applicationId is the lease application ID returned from apply and isSigned is a boolean where true indicated the customer has signed the agreement and false indicates they have not.

The signLeaseAgreementResponse object only contains signingErrors so your mutation only needs to check for the errors like in this example:

mutation signLeaseAgreement($input: SignLeaseAgreementInput!) {
  signLeaseAgreement(input: $input) {
    signingErrors {
      __typename
      ... on FatalError {
        message
      }
      ... on BadRequest {
        message
      }
      ... on NotSigned {
        message
      }
    }
  }
}

You will get a NotSigned error returned if you send false for isSigned. To resolve, the customer must agree and sign their leaseAgreement and you must retry the mutation and send isSigned as true.

Any errors returned from this mutation need to be resolved before proceeding. FatalError is caused by errors within our API. If you encounter it you should call the mutation again. If the error persists after a retry please reach out to our support team so we can help with resolution. You can reach us at [email protected]

If you get a BadRequest error you should check your input and make sure the values passed in meet the validation requirements.

Once the customer has signed the agreement, merchants should submit the purchase in their system for processing. You also need to save the orderID you used throughout this application as you will need to have it to submit your lease for funding. Continue on to our Completing an Order page to learn about submitting a lease for funding.

❗️

Cart Changes

If the customer changes their cart at all prior to submitting the purchase in your system, then you’ll need to start this section again and repeat all these steps. This is important because it ensures that lease agreement the customer signs matches the price of the purchases they’re making on your site.