Sales, Software, and SaaS: The Journey from the Client's Request to Closing the Deal [Journey in Coding] #7
June 2022, Enter Maxwell
One day in June 2022 I got a message from a guy called Maxwell. He asked me a few questions about Bank Statement Converter. Then he tells me he runs a software as a service (SaaS) business for accountants.
“Very interesting” I say, even though it is not interesting.
This is just something you have to say while doing business from time to time.
Maxwell tells me he wants something known as an application programmer interface (API). He wants this so that his application can send PDFs to my application and receive back data in Javascript Object Notation (JSON).
I tell him “Maxwell, that is a fine idea, and I will be happy to do it”. That was sort of a lie, I was willing to do it, but it didn’t make me happy.
In business sometimes you have to pretend things make you happy even when those things have no impact on your happiness.
In fact Bank Statement Converter was designed using what’s known as a “Client Server Architecture”. This means that the app is actually two apps. How about that!
One app draws pictures and tells you where to drag your PDFs. That app is known as the user interface. The other app is a much more serious guy. This app, or guy, only cares about data. You can send it data, and this guy will send you back some other data. This guy is known as the server. The server’s main job is taking in PDF files and sending back CSV records.
Ah but wait. Maxwell wanted JavaScript Object Notation instead of CSV. He also wanted the resulting data to have predictable field names. You see I just grabbed the headings from the PDF and put them into the CSV. Take a look at examples below:
Example 1
Date,Narration,Deposit,Withdrawal
10 Mar,Sushi,,100.00
11 Mar,Cola,,4.20
Example 2
Date,Description,Credit,Debit,Balance
10 Mar,Sushi,,100.00,200.00
11 Mar,Cola,,4.20,195.80
As a lazy person, I suggested to Maxwell that I do the same thing with the JSON data. He did not like this idea at all. He wanted predictable field names. What a drag. I did some thinking and I thought to myself “Well I guess I could do it. It’s not impossible”.
Eventually I ended up sending JSON data like this:
Maxwell messaged me on June 29 and by July 1 I had a JSON API for him to try out.
End of Month Numbers
July 2022, Ask for the Sale
I spent June and July resolving document parsing issues that Maxwell and his team discovered. I slowly realised this sort of work could go on forever. I decided I needed to start charging Maxwell to see if he was a serious customer or not. He seems serious but he had not given me any money yet.
I sent over this email:
Then I went to meet some friends for drinks.
You see in business, it is very important to meet your friends for drinks and perhaps get drunk. No one knows why this is a good idea, but everyone agrees it is a good idea.
After many drinks, I get a message from Maxwell asking to talk with me on Skype. I take the call. He says he doesn’t really think he should pay, because the work I’m doing to fix these documents can apply to other customers as well.
I tell him that’s true, but it’s a lot of work. I also tell him I’ve factored in a discount to account for that. We talk a bit more, we also roughly discuss a contract he’d like me to sign.
Then he says something about being limited to 10,000 documents a month. We count pages in Bank Statement Converter instead of documents. We do this because some PDFs have a ton of pages and some customers join together multiple PDFs into one file. I tell Maxwell “I think the original agreement was 100,000 pages per month, not 10,000 documents”.
This angers maxwell. I tell him why we go with pages and he says “We’re not going to join together PDFs and send them over”. I decided to drop the requirement and let him be limited to 10,000 documents a month.
I make a mental note to let him know if I see any document joining or mega PDFs.
We got to an agreement pretty quickly. Maxwell will send a big dump of documents, and then I’ll figure out how much to charge them for custom parsers.
Raising Prices
Around this time I decided to start charging based on usage. It doesn’t really make sense that a customer who converts thousands of documents a day pays the same as a customer who runs one a month.
I split the pricing into three plans: Starter, Professional and Business. The plans have monthly and yearly options. Each plan gives you an amount of credits per month or per year.
The conversion ratio drops a bit, but the higher cost makes up for this. The average revenue per user goes up. Very nice.
End of Month Numbers
August 2022, Getting Paid
Document Analysis
At the start of the month Maxwell sent me a large number of bank statements. After that I created a tool that used text, positions and images in the first page of a document to group the PDFs together. From there I figured out how many Customer Parsers need to be created.
In the dump we came across a lot of PDFs that aren’t bank statements. Things like car loan statements and mortgage statements. Maxwell agrees to ignore those. Eventually we determine we need to create 36 Custom Parsers. I asked for half the money up front and the other half on completion and sent over a Stripe payment link.
Maxwell sends it over. Okay he’s a serious customer, good!
Ambiguous Amounts
For some reason the American banks like to group their transactions into multiple tables. These tables have headings like “Checks”, “ATM Deposits”, “Cash Deposits”, “Withdrawals”, “Fees”, “ACH Withdrawals”, “ACH Deposits” and so on.
These tables will have the columns “Date”, “Description”, “Amount”. Fine whatever, no problem so far. But, there is a problem. Sometimes they will not put a minus sign in front of the debit amount. So you’ll have a table with the heading “Withdrawals” and all the amounts in that table will be positive.
Now as a human reading that table you know “Ah well these are withdrawals, so they’re debits”. Bank Statement Converter wasn’t smart enough to do that. This meant, for certain US banks, all the transactions came out with positive numbers, which made them look like credits.
What a pain eh. I wrote some code that grabbed the lines before the heading of a table. Then using those lines it determined whether or not the Amount column was actually a debit column. The algorithm goes something like this:
- Capture the lines before a table heading.
- Is there an amount column in the header of the tablee?
- Are all the amounts in the amount column positive?
- Is there text in the preceding lines like “Withdrawal, Debit, Fee”?
- If #2, #3 and #4 are true. Change the Amount column to a Debit column. Put a minus sign in front of all the amounts.
SerializedParser
At this time all my customer parsers were Kotlin class files. This meant whenever I wanted to support a document, or fix an issue with a custom parser I needed to write code and redeploy the application. It takes about 5 minutes for my tests to finish running, this means I can get something into production in about 5 minutes. Pretty fast, but writing the code takes at least an hour, even if it’s something trivial.
I started thinking about creating a UI that lets me draw a rectangle on the page. This rectangle says where the data we care about is. Then some code automatically figures out how to extract that data.
Before doing all that I spent some time creating a JSON data structure that represents the rules for parsing a bank statement. I can then store this JSON data in the database. Once that’s done I can create/edit custom parsers while the app is running.
This is really cool because it means I can get a document fixed in a few minutes as opposed to one hour.
End of Month Numbers
September 2022, Applying for YCombinator
Document Fixing
Spent most of the month fixing documents for Maxwell and other customers. Maxwell’s documents are mostly from the US and Canada. Over the last few months I have mostly been fixing documents for him.
As a result of this, customers in the US and Canada start converting a lot better. When I say “converting better” what I mean is a larger percentage of users from the US buy a subscription. This is good.
Applying for YCombinator.
I was pretty happy to get this email. They said I was in the top 10%, but who knows maybe they say that to everyone. I quickly filled in the application and recorded a video.
Maxwell Subscribes
At this point, Maxwell still wanted me to fix a lot of documents and his team hadn’t gone into production with my API. I decided it was the right time to ask him to start a monthly subscription and I sent him a Stripe payment link. He agreed and says he will pay the subscription midway through the month. Good.
End of Month Numbers
Written by Angus Cheng (Link)
0 Comments