Expensify is an expense management tool that tracks receipts, rolls them up into business reports and documents, and handles the approval workflow. Bryant has one hour to build it (or die trying).
Bryant Gillespie: Hi. Bryant here. Welcome to the inaugural episode of 100 apps in 100 hours, where I will take some of your favorite apps and try to recreate them in under 1 hour or die trying. Hopefully not dying, but you get the idea. And first on our list today is Expensify.
So we're going to build an Expensify clone. Expensify is expense management. And let's actually I'm not really sure I like the word clone here. Let's call this, a tribute, like the Tenacious d song. This is just a tribute because it would be very difficult to build all the functionality of Expensify in 1 hour.
Obviously, they've built an entire business and they probably have thousands of developers, but let's get as close as we can. So when I think about Expensify, let's just go to their website, I think of the the first thing I think of is scanning the receipt, taking a picture of it, and it does the automagic stuff, where it automatically fills out expense reports for me, which, to be honest, is kind of a pain in the rear anyway. So, that is one thing that we're going to be concerned with, the let's just map this out. Automagic Receipt Management. We're going to have expense reports.
Expense reports. So we wanna roll up all of those expenses, and, some of those are gonna be billable, And all those may be reimbursable, so we need to track for that. What else? We want to be able to approve expense reports. Seems like a good list for getting started.
Alright, so I'm gonna pull up my handy tool of choice, Directus. So Directus, for those of you who aren't familiar with it, is a back end toolkit that allows you to build pretty much anything or everything, and get instant APIs on top of any SQL database. That's the pitch. I swear that's it. Let's actually run the clock, and I'm late on the clock here, but we'll start the clock 60 minutes on the timer.
Let's go. We're gonna hop into Directus, and I am in my data model settings right now. And I'll zoom way in so you guys can actually see this alright. First thing we're gonna do is let's spec out our expenses. So let's just dive into our data model.
We're gonna have expenses as one of our collections, so Directus is gonna create this table for us. And when we go to the optional system fields, we'll probably have a status. Let's go with the sort for the order on the expense report and we'll just select all these system fields because they have some presets that are useful to us. Alright, so we've got expenses, and I'm just gonna use a Expensify attribute. We'll create a folder here for this.
We even give it like a nice green color. Boom. We're gonna organize all that inside our Expensify attribute. Okay. So the next thing, we are going to have an expense report.
Right? We've got to roll up all those expenses somewhere. This is where we'll do it. Okay. Great.
Okay. What else are we going to need? Let's just get started with this functionality. Alright. So, we go back to Expensify and let's try to figure out exactly what their data model looks like.
My favorite way of doing that, short of interacting with the app is searching for their API. So we'll just go to the Expensify API, we'll go to their API reference, we'll just zoom way in on this, Expensify integration server, all you need to integrate. Alright. So request formats, we see what's going on here. Let's look for read and get policy lists.
Maybe create. Okay. I see here's the expense creator. Alright. So, okay, it looks like here's a definition of the expense object.
So reading through this, we've got a merchant, we've got the date of the expense, we've got the amount incense, we've got the currency, that's an integer, that's probably on purpose, three letter code of the expense, external ID, there's a category, there's a tag, is it billable, is it reimbursable, Comments, reports, IDs, tax. Okay. Straightforward enough, let's dive in. We'll go to our expenses and first, let's add our merchant. So we'll just create a new field inside our data model for Directus.
This is just going to be a string type and clear enough, we are going to require value. We've got to have somebody that we got this receipt from. Let's change that to half width. And now let's move on to the amount. So let's do an input field.
Now I could do this as an integer in cents. What I'm going to do instead is just use a decimal for this. So we'll do a decimal, I could change the scale to 2 points and, looks good. Alright. So now we've got the amount for the expense, we need to add a date for the expense.
Expense date, let's just call that. So we'll choose the date time here and I'm gonna pick the time stamp as the type just because that will respect any time zones. I'm in the US. I use the 24 hour format. Or let's not use the 24 hour format since I'm in the US.
No need to include the seconds. That's great. So we got our merchant. We got the amount. We got the expense date.
Let's just do the name of the expense. Is that inside Expensify? Let's take a look. Created amounts, optional tag. Yeah.
I'm just gonna give a name for the expense. Maybe we have some notes for that. Great. We'll add the text area field for that. We don't need any formatting.
Great. Merchant amount, let's do a little cleanup on this. Directus makes it so easy to build apps that look great for your users. Alright. What else do we have?
An expense comment. Got that. So then we have things like, is this billable? Is this reimbursable? So these are going to be toggles inside Directus.
That's the name of the interface as we call it. Let's do is billable. I like to prefix those with is, just keeps things organized. Default value will be false, and looks good. Maybe we want to embellish this a little bit.
So if you go into the advanced mode inside Directus, we can add notes for our users. Is this expense can we invoice this to a client? Great. Alright. Enabled.
Let's just call it billable for the label. That seems a little better. The display is where it will show out show up in some of the different layouts inside Directus when you're looking at a list of records. Yeah. I don't see any need to change this.
Great. Alright. We'll shrink that to half width. And I'm just gonna duplicate this one, and you can see how easy it is to build this out. Is reimbursable.
Directus makes a a lot of this quick and painless. So we're gonna keep this on the expense collection. Is reimbursable. Yes. This is a reimbursable expense.
We've got the user that created this, but, I wonder if there's a a use case where I have to expenses that somebody else submitted because they didn't do their job. So let's just add a owner, an expender. What is the the proper term for that? Buyer? Let's just call it an owner.
Expense owner makes sense to me. That's what we'll call it for now. That is going to be our directus users collection. So that'll be the users of our app. Great.
That's what we'll call it. That's the hardest thing in development is actually naming things. Okay. So this looks pretty good. This is a good start.
What else are we missing for this? We've got a category, we've got the tags, Name of the tags. Yeah. We could we could do that. Let's let's build in a little more functionality.
So we'll do tags. Maybe I wanna do tags and categories as a separate collection, and actually build those into the relationships. So category to me, there's only one single category that an expense can be in. Tags obviously could be many. So here we are going to use a many to 1.
So this one, expense belongs to a single category. That's what we're gonna call it. Let's call it expense category. Great. And for our related collection, let's also do expense categories as the name of that.
Now, I could click Save and Directus will do some magic for me, or I can open up advanced mode and go in and actually look at the details of this relationship. So if we look, we can see we've got this collection, we've got an expense category field, and Directus is telling me that, hey, we're gonna create a new collection called expense categories and we're gonna use the ID field of that to populate. Alright. The mini to 1, I could control the display template, but for now I don't have any other fields because that, collection is yet to be created. But we'll go in and go ahead and create this field here.
And if I were to go back to my data model as well, we'll see that Directus created that collection for us. So now we've got our expense category. Let's go in and do tags as well. So tags are going to be a many to many relationship inside Directus. One tag could be applied to many different expenses, and many expenses could have many different tags.
Great. You didn't know we were getting into data model expertise today, but let's name this thing. What are we gonna call it? We're just gonna call it tags. Right?
We're going to create a related collection called expense tags and what else do we need to do? Show a link to the item so we can edit that tag as needed. Great. Save. Alright.
So now we've got the basis of our expenses. Let's go in and flesh out these other ones that we just created. For expense categories, we're probably gonna have a name for that expense category. And, you know, maybe we got, like, an account number for our profit and loss, account name. Cool.
Alright. And then for our tags, let's go in and add name and maybe we want to create a color for our tags. So I'm just gonna search for the color field here inside Directus. We'll give each tag a color. I could go through and preset these.
If you leave this blank, Directus will actually create, give you a few of those presets that look nice anyway. Alright. So always gotta do my proper formatting. This is kind of a speed run, but one of the other things that I am a little OCD about, honestly, is cleaning things up and having a nice row of or nice columns of icons inside the app. So you can see a website project I've got working on here, but, you know, for now let's just roll with this.
So we've got our tags, we've got our categories. The last thing that we need to do, if we open up one of our expense reports, which we have no data in that. We need to figure that one out. But we need a link back to our expense reports. So let's go into the data model.
We'll go to expense reports. And this is really nice. We just recently added this search feature inside the data model, which is great, especially when you have hundreds of collections. So we'll go into our expense report. We're going to have a name.
Do we even need a name? Yeah. We'll give it a name of the expense report. This could be a title. Bryant's second quarter expenses, blah blah blah, etcetera.
Alright. Then we have a owner or could be like submitted by, you know, that's probably better but we stuck with owner on the other one so we'll just roll with that. For our related collection, we're gonna do direct us users. And you could pick these from a drop down over here on the right just by clicking those, but if you'll notice when I hit on one of the actual collections inside Directus, this turns purple just to let me know I'm doing the right thing here. So we got the owner of this expense report, yeah, I don't like that terminology, but I I don't wanna backtrack at this point.
Date created. Alright. What else do we have? Then we're gonna need the actual expenses on this. So in this case, we've got a one to many relationship.
So one expense report has many expenses. We're gonna call the key for this expenses, that's what it's gonna be stored as a column in the database as, and then we're going to pick our expenses as the related collection. And for the foreign key, we don't have one that exists already, but Directus will create one for us, which is nice. We're just gonna call it expense report because there is a single report it is linked to. And then I could go in and use the let's change this to a table view.
We could see the merchant. Maybe we want to add the expense date, the amount, and, maybe the category. So here when it's a related collection I can just pick up the the related fields as well. Great, enable searching and filtering, hit save and it's probably good enough for now, right? Let's dive in and actually start creating some expense reports.
So, I've got a new expense report. Brent's 4th quarter, it's not even the 4th quarter, 3rd quarter, let's just call it September expenses. Expenses. Great. Alright.
So we go in, I'm gonna be the owner of this. I am not a user at this point, so I'll just use mister hop along. And now we can go in and add some of our expenses. Alright. So we've got Starbucks.
The expense date is going to be this morning at, what, 7:30. I'm in West Virginia of all places, so we don't have a a ton of coffee options here. I know some people are gonna be mad that we've got Starbucks in here. That was expensive. So let's say 2102 has the amount.
Coffee Needed that real bad. Alright. Is this billable? Probably not. Is this reimbursable?
You know, we could have this where I could select this, but one of the other things you could do inside Directus is preset this to a default setting for, like, the the current user, for example. So for now, I'll just pre we'll pick hops along. We don't have any expense categories. I wanna say this would probably fall under meals and entertainment or just meals. No, you wanna divide those out.
I hate doing bookkeeping, so accounting account number, I wanna say it's like the 3 or 4 100. Mills Entertainment. Great. Cool. Keeping track of all that.
Tags. What are we gonna tag this as? Coffee would be the name of it. I don't really like any of these. Maybe we can pick, yeah let's just go with red for coffee.
That's great. Cool. Alright. So we've got our information here. We've added our first expense.
Pretty great. Cool. We've got our expense report. Yeah. The next thing maybe we want to fire off this expense report to somebody on our team.
How are we doing on time? We're at 43 minutes, so that took about, 18, 20 minutes to flesh out this. How can we send this expense report to a team member, for approval? Well, first of all, let's do an expense report. Let's add an approved by.
So we wanna track who this was approved by. That's gonna be a directus users, so it's gonna be one of our users. Great. And then maybe an approval date, Right. So we'll do a date timestamp, date approved.
Great. No 24 hour format. So now we got 2 fields to track our approvals. Let's go in and use the flows inside Directus to send this report off or send a link to somebody to this report. So send expense report for approval.
Great. And then we can even customize this. Let's do send. Yeah. There we go.
Looks great. Scheduled send. We'll make this orange just so it stands out. Alright, so now I've got a list of different triggers. I want to actually trigger this one manually.
So Directus gives us the option within a specific collection on the layout page or the detail page to send this off. So we will go in and look for expense reports. Okay. There's my expense report. Great.
And then I could choose whether this is asynchronous. So, you know, do I wanna do this in the background? What are the locations where I can trigger this? So we wanna do on the collections and items pages. That's fine.
We'll do both of those. If you are on the collection page, this will require a selection. We we do need you to pick this to actually send this off. And then next I'm gonna do this require confirmation because I get the ability to add different fields to the system, to prop for those fields when I send it. So I am going to add a new field for approver.
So who do we need to send this? Approver. Who needs to approve this report. Great. Now the type I'm gonna pick here is gonna be JSON because we have a special little interface called the collection item drop down where I can pick a value from this and store it in JSON.
So here again, we're gonna do directus users, and I'm gonna pick the user that I want to approve this report. And I could go in and as far as customizing the display template as well. You know, let's do the avatar, first name, last name. Great. And then maybe we even wanna add a note.
Note. Close note to approver and that'll be just a simple string. No big deal. Great. Got the field width, let's make it full width.
Actually, let's do a text area for that. Just a quick note. Great. Okay. So now that we've got that, what I'm gonna do, I'm gonna save this and I just wanna get a look at what it's gonna look like when I'm on my expense report.
So over here on the right hand side, you can see Send Expense Report for Approval. I can select items or if I'm inside this expense report, I can click expense report, and then I get this confirmation dialogue of who needs to approve this, Matt. My note to Matt is going to be, hey, I need more budget for these videos. Great. Run flow on current item and let's just see what that came up with.
So inside my flows, I can go in and check my logs and I could see what was actually sent down the pipe. So here's the trigger, here's the body of the payload, and this is actually what we received. This is what we will use to fire off that message. Alright. So this looks great.
What I'm going to do, I'm just gonna copy this information, this is what I need, and I open up Versus Code. Let's start with a new window here. Where are you? New window. New file.
Alright. So this is our trigger data. Great. Perfect. Okay.
So now let's build the steps of our flow. We wanna send this expense report for approval, but we need an email to send it to, and we do not have that data here. So we need to actually get that data. So that's gonna be our next step. Get approval approver email is what we'll call it.
And we will click read items from the database. The permissions from the trigger should be fine. I can also change this to full access if this is gonna be, triggered from somewhere other than inside the app. And for the collection we are going to use the directus users, but you can see this is not coming up in the search because it's a system collection. So I'm just gonna go in and hit edit raw value and we will do directus underscore users.
That's our collection. Now for the IDs, we are going to use our little squarely bracket mustache syntax and we are gonna pick up the ID from this approver key that we selected. Alright, so, how do I do split screen here? Fancy fancy. Alright.
So this is gonna be located at, so we use our brackets, mustache, we're gonna do dollar sign trigger. Trigger is the only one that has a special syntax. All the other keys of your operations get appended under, the key that you set here without the dollar sign. That's one of the big things that I see a lot of people get tripped up on. And it's gonna be dot body dot approver.key.
Great. That's gonna be our ID. Do we need a query for this? I don't think so because we're picking up the key there. Let's hit save and then next we want to, I'm I'm just gonna save this.
Let's run that one more time. So we'll go back to our expense reports. I'll pick Matt here. Hey, dude. We'll go back to our flow, and this is a good way of building flow so I can actually see the details of what we've got going on.
Now I can see an issue right away. This for this demo anyway. This is gonna send to matt@example.com, which is not a real email address. So I'm just gonna quickly change this to one of my own emails just for demonstration purposes and to prove that we can actually build this app this quickly. Alright, we'll go back to our flows.
Now let's actually send that email, and again when working with flows it's helpful to have like a code editor open, but, this case is fairly straightforward. We are going to send an email. We'll choose the send email operation and for the addresses we're gonna use that squirrely mustache syntax again. This is going to be get, this is where my memory struggles. This is called git approver email.
So the 2 is gonna be git_approveremail, and that's gonna be the user object. So we're just gonna do email. I have to hit enter here to save this. We could also add additional emails if I wanted to if I wanted to cc myself. Let's call this expense reports.
And the type here could be WYSIWYG. You can even choose a template if you are using our custom extensions, but let's go in do this as a WYSIWYG will be fine and we're going to do the trigger. So we we just want to pick up the content from our notes, which is gonna be body dot note. Should be Great. Alright.
So this should populate that message into our WYSIWYG editor when we send this email out. Fingers crossed we're gonna save this. Let's test it out and see. How we doing on time? Alright.
So we got about 32 minutes left, maybe a little less than that because I was, failing on throwing together the or I was failing to do the the countdown correctly. But, let's give this a shot. We'll go in, we'll send the expense report for approval, and we're going to send it to Rabat Miner. I need some more lattes. Alright.
So we fire that off. Let's go back in and check our logs just to make sure. And it looks like the email went out. I'm just gonna open up my email inbox and voila, it it sent this out. That's great, that's all good, but, where's the actual expense report?
There's no link. So let's go back in and what I'm gonna do, I'm just gonna capture the URL for this from my directus admin. Great. And then we're gonna go into our flow. We'll go back to that email and we just wanna give Matt like a button or a link or something here.
So we're gonna do view and approve report. We'll enter in this email and we're gonna use our bracket mustache syntax and we'll do the trigger dot body dot keys 0. So the first item of the keys array is what we want to include. Cool. Great.
Gravy. Save. Save. Alright. So now let's go back in.
We'll send this expense report one last time, one more time with a link, hopefully. Fingers crossed, right? Alright, so now we wait and boom, we have a link. We click on the link, it logs us in and, Matt should be logging in to update the status on this. So we may want to go in and update the statuses for these.
Let's do our expense reports. Let's change the status, draft. We'll do submitted for 1. Submitted. So submitted for approval.
Approved. Maybe not approved is 1. Rejected. Let's call it rejected. That'll that'll be fun.
That's a little harsh for an expense report, like, hey, your expense report was rejected. But, yeah, no worries. Oh, I goofed that up, didn't I? Should've saved before I started slamming away on the keyboard. Submitted.
Alright. We'll just clean this up. Draft. Okay. Approved.
Rejected. Alright. Let's just show the raw value for now or maybe a formatted value. That's fine. We'll do like a border, make it fancy looking, allow other values, no, allow no selection, no, for the interface though maybe it could be interesting if we do radio buttons.
Great. Alright. Cool. So now we go in. Matt can approve this expense report and save it.
But as you can see, I'm logged in as myself. I could potentially approve this expense report myself, which is is not cool. So we could use the roles and permissions inside Directus for that, where I could go in and say a given role like if we just had one called team member for example, I could go in and for our expense reports, I could go in and give custom permissions for this so that I cannot edit a certain field like the status. So this would prevent that user from actually, I'm sorry. I did that backwards.
I would check all the other fields like the that user can update everything else about this expense report except the status or any other items that were that I needed. And likewise, one of the other things that I could do here is when I create a report, if we use the custom permissions for this, you could go in and define the presets where you can say, hey the current user is the default for this particular field. Sounds great. Alright. That is basic functionality of this.
We've got the ability to add expenses, submit expense reports. You know, you might wanna try and tag into some other system to pay out these expenses, but for now I could stroke a check for those, I guess. But that leads us back to, boom boom boom, the automagic receipt management. So this part is a bit scary scary to me. I don't know how we're gonna do this in 26 minutes.
Actually, I'm lying to you. I do know, what we're going to try because I've already cheated a little bit. Let's get that clock out of the way. I'm gonna make this full screen again. I have found this other service called Mindy Mindy?
Mindy? Not sure what it's called, but it takes the receipts OCR, optical character recognition magic on them and apparently spits back out some data. Now, for the sake of time, all I've done is logged into this app and, set up an account. I haven't done anything else with it, so you're almost as fresh as I am at this point. I did see just a quick little tour tooltip that told me this is the API that I want.
So let's take a look at at how we could do this. Anytime I upload an expense that has an image attached to it, and Directus is mobile friendly, so I could potentially log into this from my phone and update these expenses as well, just to to prove it to you there. Anytime I update one of those expenses, it has an image attached to it. We wanna send this off to this service and hopefully, I'd, like, not have to deal with actually entering in all the separate fields. Great.
So first thing we need to do is, we got our expenses, let me close this one. We need to add an image field to upload the expense. So we'll go into our expenses. Let's add a image, receipt image or receipt file or we could just call it file. No need to get fancy with it.
Alright. So now we've got the ability to upload a file. Let's start building a flow and then we'll incorporate this other service. So we've got, automagic COCR. Cool.
Alright. So we'll do that on a vinthook. Let's do a action non blocking, so we don't wanna block the thread. Anytime a new item is created inside expenses, and we'll start there. Right?
Alright. So let's go into, let's actually go back to our expenses. Let's just call this a new expense. Actually, we're not gonna do any of that. All I wanna do here and maybe we move this file up to the start actually.
Let's move our file way up here. Alright. So the ideal scenario here is all I have to do create a new expense, upload an image of that, and then this service and Directus would do the rest for me. So let's just Google receipt images. Let's get a receipt image, see if we can find one that's pretty gnarly as well.
What's this guy? Tesco Metro. Yeah. This one looks pretty beat up. This will be a good test, right?
Save this image. Where did I go? Too many different tabs going on. So here's our Tesco shopping receipt. We hit save.
Merchant value can't be null. That was a problem of mine, maybe I should go in and remove that, but you could set that up where it wasn't required. But now, if we take a look at our flow, that should have triggered our flow, we've got a payload, we can see here's the file that we're going to potentially pick up. Great. One of the other things that I wanna make sure, because we're gonna have to send this file to that service, is I'm gonna check our system collection and make sure that direct us files has public read permissions, and I could drill down to where, you know, only, files within a certain folder are available if I wanted to get very specific for this.
Let's just leave it as is. Again, this is an Inexpanify Tribute, not a clone. Great. Alright, so now we've got our data coming from our new expense, we are going to wanna pass that to the mindd API. So let's see the API here.
Alright. Load some stuff up for me. Alright. If I was smart I would have gone in here and cheated a little bit more than what I'm doing now. Alright.
So I don't have an API key. How do I create an API key? API keys. Alright. We'll create an API key.
We're gonna call this Directus. Great. Copy that API key. Don't you guys steal my API key? So So we'll go back to the API, go back to our documentation.
Here's everything we're gonna need. Now is a good time to do the split screen stuff with, Arc. Great browser, still struggling, like 6 months on to figure this thing out. Alright, give myself a little more room. So we got the post request.
We are going to use the send to, let's just call it OCR receipt. We are going to use the webhook request URL. We're gonna do a post request as it says. Here is our URL that we're gonna pick up. Hopefully, we could just copy that.
Savvy. Of course it takes that post request. This looks okay. We got our headers, we're gonna add authorization. It's gonna be a bearer token.
Raycast, great app as well, by the way. We'll paste in our API key and then the content type. Content type. Multipartformdata. K.
Let's look for, like, a curl example. Document is path to your file. Okay. So it looks like we've got a document key and I'll pick up oh, the other downside of working locally. That might be the death of this particular project.
Right? This is on my local computer. I've got 18 minutes. It's not going to be able to access that image. Let's do some more cheating.
Right? Go back to our receipt images. I got the image address. Don't be mad at me for cheating on this. Alright.
Let's take a look at that. We got a document. Here's the public URL of an image. Document can either be a file object URL or base 64. That should be savvy.
Next time I'll have to do this on a standard cloud instance, not one of my local copies. Alright. So we got this. We're gonna take the webhook request. Let's see if they give us like a response what that response looks like.
Date, confidence, document type, line items, locale, supplier address. I tell you what, let's just send this off and see what we come back with. Alright, so we're just going to pretend and actually this is gonna be correct because it's the same receipt but just a little cheating involved. We'll add a merchant name for this, We've sent this off to our auto magic receipt. It says unauthorized.
Use token. What did I forget? Oh, token. Let's see. I've forgotten something.
API reference authorization token. It's not bearer token. It's just token. Great. Let's go back and try her again.
Keep editing. Don't forget to save your changes, kids. Alright. We'll create a new expense. Use the same receipt we've already uploaded so we don't duplicate it, and I really should remove that requirement.
Go to our flows, See what we got. Bad request. Missing boundary and multipartform data. Alright. How are we gonna structure this, right?
Missing boundary and multi part form data. Do we actually need the content type? Can we try that? See if we can get away with it. Otherwise, I think I'm gonna have to reformat everything.
Alright. So we go to our flows. Let's take a look. Logs. Hey.
There we go. Alright. So we've got our prediction. And we probably don't have to use form data because we're not passing an actual document. Cool.
So we've got our document. This is a giant string, or a giant JSON object. Tons of stuff. Taxes, the value, supplier phone number, prediction, document type, expense receipt. Here's our line items.
We just need our amount, right, and dates. So I'm just gonna copy this whole thing. Let's open up Versus Code. Do this and we'll look for date. Okay.
So there we go. We've got our date. It'd be great if there was a way to copy that path. Right? Let's close, let's separate these, do this, do a little side by side action going with Versus Code.
Alright, so now we need to update this item. How we doing on time? We've got 13 minutes. Let's get it done. So now we're gonna update our expense with the data coming from this API.
And I may wanna do something like this where we say format data or I could just directly update that data. Anyway, so we'll go into update data, let's say update expense. We are going to use the permissions from the trigger, this is gonna be an expense. The IDs are gonna be coming from trigger dot body, dot keys dot 0, I believe. We'll take a guess and the payload that we want, we got the merchants.
We wanna pass that. We want the expense date, I believe. The amount of the expense, and I think that would be a win. So let's look for the merchant, supplier, supplier address, supplier name. Alright.
Let's start with the date. Right? So how do we get a hold of this guy? We've got our data. Alright.
Let's just save this. That is our OCR receipt. That's our key. And of course because this is an invalid payload, it did not save. Alright.
So our date expense date is going to be blah blah blah. We've got, OCR receipt dot data dot documents dot inference. I love that these guys are saying all this, dot pages dot prediction, debugging this is gonna be a nightmare, dot date dot value. That is deeply nested if I've ever seen it. Great.
Alright. So next we've got the merchant. Let's try it. That is gonna be something probably similar, and I already see a typo. Prediction.
Okay. So we'll just copy paste that. Alright. And that's gonna be called what? The supplier supplier name value prediction dot supplier underscore name dot value.
Okay. Great. And then last but not least should be the amount. And we are closing in on 10 minutes on the clock, hopefully this thing works out. Would hate to start off on a loss.
Alright. So the amount let's look for the amount. Total amount is what we're looking for. Point 99 confidence, that's great. That's what we're looking for.
Got a lot of confidence in this. We got the total underscore amount dot value. Alright. So there we go. We've got our JSON.
I'm just gonna copy it just to verify, update. Let's try it one more time. Let's delete these failed attempts. Alright. Tesco shopping receipt.
We're gonna have to enter that in. Hit save and automatic receipt OCR. I don't have permission to access this because I don't have the proper key. So I didn't pass the key. I got the payload wrong as well.
What did we get wrong here? Dot data, OCR receipt dot data dot document. Maybe it's just document. Maybe we can omit data. OCR receipt.
And I also need to fix the keys because I didn't get those correct either. So it's actually just key. That's what's coming from the trigger, the expense. So body trigger dot body dot key. Alright.
Fingers crossed. We'll run this again. This works this time. Let's hope so. Do our nice little t here.
Boom boom boom. You don't have permission to access this. Still says undefined. So we're getting this back from the API. That's great.
Trigger dot body dot key. The key should be correct, though. Payload trigger dot payload oh, no. This is an event hook. I'm sorry.
So I've got it wrong. Should just be trigger dot key. No body. It's fine. Trigger dot key.
That part's good. We are not good here, though. So let's do this. Let's disconnect this. Let's add a step.
You just log this to the console. Log. And we are going to do get OCR receipt is what we're calling it. We're just gonna console log OCR receipt. Log OCR receipt.
See what we're getting past. Alright. We'll drag that down here for now. We are running out of time for like a fun playing beat the clock. We'll hit save this.
Let's go take a look. What do we got for him, Johnny? Log to the console, message dot data. Okay. So do we have to include message dot data?
Worth a shot. Let's see. With 5 minutes and 40 seconds on the clock, Wasting precious time. So we have message dot data Message dot data dot documents. I'll just copy, paste.
Alright. It's either gonna be a big finish or a sad ending. Not sure. We'll try it out and see. Alright.
So we've got that same image, we're running it one more time. Flows do us nicely error update expenses set where invalid input syntax for type numeric. Still not getting the correct stuff coming from the app here. What in the world is going on? Alright.
Let's bring in the big guns here. What are we what am I doing wrong? Logging to the console. Alright. Let's try picking up the data that we want.
Let's go with, run scripts. Where are you? Format, data. Alright. So we're gonna get the data from receipt equals OCR data dot OCR receipt.
Okay. And let's just return receipt for now. Let's string this together. Let's see if I could just get something going here. Format data.
What's going on? It's gonna be a sprint to the finish. To to to log to the console. I can't even get my, so we'll drag that. Let's log into the console.
Let's see what comes out of this. Expense, save, format data, flows, auto magic. Alright. So we got the run script, status. Okay.
So we got data. We wanna pick up the data dot document. Right? I swear that's right. Data.ocrdoc equals receipt dot data dot document.
Let's return the dock. We'll just keep drilling down. We got 2 minutes left. Let's see how this is gonna play out. Save t.
Save it. Flows. If I was smart, I would have had multiple options. Okay. So we got this.
Let's get down to our inferencing. Oh, I see what was wrong now. Duh. Pages is an array. That's where we were going wrong the entire time.
Pages 0. Don't you love that? Message. It's not message. The message is coming from that console log.
Alright. So with 1 minute and 21 seconds on the clock, let's save this and just see what comes up as the clock is ticking down. T. Now, if I hit save and stay it should be doing that for me, but it did not. However, did it?
Did it actually do it? Expenses. There it is. Boom. With 49 seconds on the clock remaining, we have populated the receipt information from a third party API.
Therefore, fulfilling our requirements for this, That is a wrap on the first edition of 100 Apps in 100 Hours. I feel like we need like a little Tiger Woods just, yeah, finish up strong. So if you enjoyed this series, or this episode of this series, stay tuned. We've got more coming like this. Would love for you to hop into our Directus Discord community and send us your feedback on what apps you would like to see us build next with our set of tools that we have here at Directus.
Can Bryant follow AirBnb's trajectory from scrappy startup to short term rental royalty – and build an AirBnb clone in one hour or less? Follow along as he attempts to builds a complete backend and frontend to manage rental listings, bookings, hosts, and more.
From idea to MVP in hours. Learn how two entrepreneurs built, launched, and continuously iterate on an all-in-one ecommerce platform from the ground-up.
It's Bryant vs the streaming giant – Netflix – in this exciting episode. He has just one hour to build an app that replicates the core functionalities of the video streaming service.