Skip to main content

Tutorial

In this tutorial we'll run through the process of creating everything necessary for syncing Order data from a POS to the Loaded system. This covers the majority of what a client integration is going to need to do so is a good reference for understanding the development work required as part of your own integration with us.

tip

We're going to make use of External IDs in this tutorial. If you've not already read the Core Concepts section now's the time to do that before continuing on!

Getting started

Get authenticated

You'll need to have negotiated a bearer token in order to send API requests. In this tutorial we won't go into details of how to do this, but the expectation is that you'd use a OAuth2 library and have retrieved an access token and refresh token based on the credentials you've been given by Loaded.

caution

You'll need to have a mechanism in the final version of your code that can refresh the access token. Access tokens have got an expiry time and will stop working once that has passed.

Our menu

Lets assume that our POS system that we're syncing to Loaded has got a simple menu that customers can order from that looks like the following:

Our Menu

Food

Brunch

BLT Sandwich - $20 option to add an Egg +$5

Granola Bowl - $15

Dinner

Steak & Fries - $40

Market fish - $45

Dessert

Fruit Salad - $15

Beverage

Hot

Espresso - $5

Latte - $7

Cold

Cola - $4

House Lager - $10

Setup the menu in Loaded

We'll start by creating our menu in Loaded. To do that we'll first need to create categories and subcategories within Loaded that we wiill ultimately create the menu items within.

Create the categories

We need to send POST requests to the /pos/categories endpoint to create the Food and Beverage top level categories for our menu.

The JSON object we send looks like the following:

{
"name": "Food",
"externalId": "my-food-category-id"
}

the value of the externalId property, my-food-id is just an example value - for your integration you'd use the id value of the equivalent of the Food menu category in your own systems database.

So to create the Food and Beverage categories we've got to send a couple of requests:

curl \
-X POST \
-d '{ "name": "Food", "externalId": "my-food-category-id" }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/categories

and

curl \
-X POST \
-d '{ "name": "Beverage", "externalId": "my-beverage-category-id" }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/categories

Those categories should now be created. You can check what Loaded has by sending a GET request to the /pos/categories endpoint:

curl \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/categories

all going well you should see something like the following returned to you:

[
{
"id": "95efe6d0-d3f9-44f5-122e-08db7b5110ec",
"externalId": "my-food-category-id",
"name": "Food"
},
{
"id": "ff95ede8-1dc2-450f-ac9a-cebe60b0ec88",
"externalId": "my-beverage-category-id",
"name": "Beverage"
}
]

Create subcategories

Now we've got the Food and Beverage categories ready to go we can create the subcategories that sit under those, for Food that is the Brunch, Dinner, and Dessert levels; for Beverage it's Hot and Cold.

We need to send POST requests to the /pos/categories/<category id>/subcategories endpoint to create the subcategories for our menu.

The JSON object we send looks like the following:

{
"name": "Brunch",
"externalId": "my-brunch-subcategory-id"
}

in the request url we are going to use the external id value to reference the categories that we created earlier. This is as simple as prefixing the external id we created, e.g. my-food-category-id with eid:.

So to create the subcategories now here are the requests we need to send:

curl \
-X POST \
-d '{ "name": "Brunch", "externalId": "my-brunch-subcategory-id" }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/categories/eid:my-food-category-id/subcategories
curl \
-X POST \
-d '{ "name": "Dinner", "externalId": "my-dinner-subcategory-id" }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/categories/eid:my-food-category-id/subcategories
curl \
-X POST \
-d '{ "name": "Dessert", "externalId": "my-dessert-subcategory-id" }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/categories/eid:my-food-category-id/subcategories

and

curl \
-X POST \
-d '{ "name": "Hot", "externalId": "my-hotdrinks-subcategory-id" }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/categories/eid:my-beverage-category-id/subcategories
curl \
-X POST \
-d '{ "name": "Cold", "externalId": "my-colddrinks-subcategory-id" }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/categories/eid:my-beverage-category-id/subcategories
tip

Notice how the urls reference the Food and Beverage categories using our own IDs (my-food-category-id and my-beverage-category-id). We could have used the ID values returned from the Loaded API after creating the categories initially, but that would mean that our client code would have to store those somewhere. Given we have our own IDs it's easier to just use our own.

Create the menu items

We're now ready to create the items underneath the subcategories sorted out above. The same process is used, POST requests to the /pos/items endpoint this time.

The JSON object we send looks like the following:

{
"categoryExternalId": "my-food-category-id",
"subcategoryExternalId": "my-brunch-subcategory-id",
"externalId": "my-blt-item-id",
"name": "BLT",
"price": 20
}

So to create our menu items here are all the requests we need to send:

curl \
-X POST \
-d '{ "categoryExternalId": "my-food-category-id", "subcategoryExternalId": "my-brunch-subcategory-id", "externalId": "my-blt-item-id", "name": "BLT", "price": 20 }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/items
curl \
-X POST \
-d '{ "categoryExternalId": "my-food-category-id", "subcategoryExternalId": "my-brunch-subcategory-id", "externalId": "my-granola-item-id", "name": "Granola", "price": 15 }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/items
curl \
-X POST \
-d '{ "categoryExternalId": "my-food-category-id", "subcategoryExternalId": "my-dinner-subcategory-id", "externalId": "my-steak-item-id", "name": "Steak & Fries", "price": 40 }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/items
curl \
-X POST \
-d '{ "categoryExternalId": "my-food-category-id", "subcategoryExternalId": "my-dinner-subcategory-id", "externalId": "my-fish-item-id", "name": "Market fish", "price": 45 }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/items
curl \
-X POST \
-d '{ "categoryExternalId": "my-food-category-id", "subcategoryExternalId": "my-dessert-subcategory-id", "externalId": "my-fruit-item-id", "name": "Fruit Salad", "price": 15 }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/items

and

curl \
-X POST \
-d '{ "categoryExternalId": "my-beverage-category-id", "subcategoryExternalId": "my-hotdrinks-subcategory-id", "externalId": "my-espresso-item-id", "name": "Espresso", "price": 5 }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/items
curl \
-X POST \
-d '{ "categoryExternalId": "my-beverage-category-id", "subcategoryExternalId": "my-hotdrinks-subcategory-id", "externalId": "my-latte-item-id", "name": "Latte", "price": 7 }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/items
curl \
-X POST \
-d '{ "categoryExternalId": "my-beverage-category-id", "subcategoryExternalId": "my-coldrinks-subcategory-id", "externalId": "my-cola-item-id", "name": "Cola", "price": 4 }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/items
curl \
-X POST \
-d '{ "categoryExternalId": "my-beverage-category-id", "subcategoryExternalId": "my-colddrinks-subcategory-id", "externalId": "my-lager-item-id", "name": "House Lager", "price": 10 }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/items

There's one final item we need to create, this one is slightly different as it's an item modifier - we use this to represent the fact the BLT menu item can have an item optionally added to it.

The JSON for this is pretty much the same as a normal item, we just have to flag that it's a modifier by setting the type property to the special value Modifier.

{
"categoryExternalId": "my-food-category-id",
"subcategoryExternalId": "my-brunch-subcategory-id",
"externalId": "my-blt-egg-item-id",
"name": "Egg",
"type": "Modifier",
"price": 5
}

Here's the final request to send to set up all our menu items:

curl \
-X POST \
-d '{ "categoryExternalId": "my-food-category-id", "subcategoryExternalId": "my-brunch-subcategory-id", "externalId": "my-blt-egg-item-id", "name": "Egg", "price": 5 }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/items

Setup a staff member

Now all the menu items are ready for use in Loaded we just need a staff member to reference in our orders. Unsurprisingly we do that by sending a POST request too. This time the endpoint to use is the /pos/staffmembers one.

info

If your POS system doesn't have the concept of staff members you can skip this step. The API will accept orders being created without a staffMemberId reference. Of course if you do have staff members, it's best to send the data to Loaded to ensure the best possible experience for users.

The JSON for creating a staff member looks like:

{
"externalId": "jane-doe-id",
"firstName": "Jane",
"lastName": "Doe",
"dateOfBirth": "2000-01-02",
"status": "Active",
"remuneration": {
"type": "Wage",
"baseRate": 25.00
},
"role": {
"name": "Front of House"
}
}

Our pretend POS system has a staff member called Jane Doe so send the following request to set her up in Loaded:

curl \
-X POST \
-d '{ "externalId": "jane-doe-id", "firstName": "Jane", "lastName": "Doe", "dateOfBirth": "2000-01-02", "status": "Active", "remuneration": { "type": "Wage", "baseRate": 25.00 }, "role": { "name": "Front of House" } }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/staffmembers

Send the first order

We're now at the point where we can start sending orders to Loaded. In practise all the steps above won't happen too frequently, but sending orders into Loaded will be happening all the time. An Order in Loaded tracks a customer asking for something, and that being processed on the POS. Payment for whatever was ordered by the customer is also attached to the Order in Loaded - as a Tender.

In this first example we're going to send an Order that represents a counter service interaction where the customer has requested and paid for a Espresso from our menu all in one go (i.e. there's no tab or table service involved). Our staff member called Jane Doe has handled this transaction and the payment was processed using cash.

The JSON for our Order looks like the following:

{
"externalId": "my-order-id-1",
"createdAt": "2023-07-02T11:30:00Z",
"completedAt": "2023-07-02T11:30:00Z",
"status": "Completed",
"staffMemberExternalId": "jane-doe-id"
"items": [
{
"externalId": "my-espresso-item-id",
"requestedTime": "2023-07-02T11:30:00Z",
"quantity": 1,
"unitPrice": 5,
"unitTax": 0.65,
"settlementStatus": "Paid"
}
],
"tenders": [
{
"externalId": "my-tender-id-1",
"tenderedAt": "2023-07-02T11:30:00Z",
"type": "Cash",
"invoiceAmount": 5
}
]
}

Lets send that request off now to create the Order:

curl \
-X POST \
-d '{ "externalId": "my-order-id-1", "createdAt": "2023-07-02T11:30:00Z", "completedAt": "2023-07-02T11:30:00Z", "status": "Completed", "staffMemberExternalId": "jane-doe-id" "items": [ { "externalId": "my-espresso-item-id", "requestedTime": "2023-07-02T11:30:00Z", "quantity": 1, "unitPrice": 5, "unitTax": 0.65, "settlementStatus": "Paid" } ], "tenders": [ { "externalId": "my-tender-id-1", "tenderedAt": "2023-07-02T11:30:00Z", "type": "Cash", "invoiceAmount": 5 } ] }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/orders

In response to the creation request we'll receive a response that shows the content of the Loaded system for this Order. It should look something like the following:

{
"id": "f7b260b8-bbc9-40b4-bb05-571d66e5eeac",
"externalId": "my-order-id-1",
"createdAt": "2023-07-02T11:30:00Z",
"status": "Completed",
"completedAt": "2023-07-01T11:30:00Z",
"staffMemberId": "67241672-876a-43d4-e6b9-08db7b51187a",
"items": [
{
"id": "76f8ea13-ba75-46c5-213b-08db7b511ace",
"posItemId": "0124057a-a9ae-4fe3-5762-08db7b5119b8",
"externalId": "my-espresso-item-id",
"quantity": 1,
"unitPrice": 5,
"createdAt": "2023-07-07T02:41:25.3233333",
"discounts": [],
"surcharges": [],
"settlementStatus": "Paid",
"modifiers": []
}
],
"tenders": [
{
"id": "e5a0212f-7c5e-43c5-4eea-08db7b511c6e",
"externalId": "my-tender-id-1",
"tenderedAt": "2023-07-02T11:30:00Z",
"type": "Cash",
"invoiceAmount": 5,
"taxAmount": 0
}
]
}
tip

You can use the GET endpoints of the API during development as a means of exploring what data Loaded has got in it. In this case we can query for our specific order by sending a GET request to https://api.loadedreports.com/v1/pos/orders/eid:my-order-id-1. If you wanted to see all the Orders in a time range you could call the https://api.loadedreports.com/v1/pos/orders?from={startTime}&to={endTime} endpoint.

info

In Loaded both the Orders and Sales reports will now be showing $5 in the 11am hour. This represents the espresso being ordered and then paid for in this period.

Order an item with a modifier

Lets imagine that a customer has now come to the coutner and ordered (and paid for) a Latte and a BLT, but they'd like to add an Egg to the sandwich. Jane Doe has served them again, and they've paid using a Visa credit card.

The JSON for our Order looks like the following:

{
"externalId": "my-order-id-2",
"createdAt": "2023-07-02T11:45:00Z",
"completedAt": "2023-07-02T11:45:00Z",
"status": "Completed",
"staffMemberExternalId": "jane-doe-id"
"items": [
{
"externalId": "my-latte-item-id",
"requestedTime": "2023-07-02T11:45:00Z",
"quantity": 1,
"unitPrice": 7,
"unitTax": 0.91,
"settlementStatus": "Paid"
},
{
"externalId": "my-blt-item-id",
"requestedTime": "2023-07-02T11:45:00Z",
"quantity": 1,
"unitPrice": 20,
"unitTax": 2.61,
"settlementStatus": "Paid",
"modifiers": [
{
"externalId": "my-blt-egg-item-id",
"unitPrice": 5,
"unitTax": 0.65
}
]
}
],
"tenders": [
{
"externalId": "my-tender-id-2",
"tenderedAt": "2023-07-02T11:45:00Z",
"type": "Visa",
"invoiceAmount": 32
}
]
}

And sending that request off to create the Order:

curl \
-X POST \
-d '{ "externalId": "my-order-id-2", "createdAt": "2023-07-02T11:45:00Z", "completedAt": "2023-07-02T11:45:00Z", "status": "Completed", "staffMemberExternalId": "jane-doe-id" "items": [ { "externalId": "my-latte-item-id", "requestedTime": "2023-07-02T11:45:00Z", "quantity": 1, "unitPrice": 7, "unitTax": 0.91, "settlementStatus": "Paid" }, { "externalId": "my-blt-item-id", "requestedTime": "2023-07-02T11:45:00Z", "quantity": 1, "unitPrice": 20, "unitTax": 2.61, "settlementStatus": "Paid", "modifiers": [ { "externalId": "my-blt-egg-item-id", "unitPrice": 5, "unitTax": 0.65 } ] } ], "tenders": [ { "externalId": "my-tender-id-2", "tenderedAt": "2023-07-02T11:45:00Z", "type": "Visa", "invoiceAmount": 32 } ] }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/orders
info

In Loaded both the Orders and Sales reports will now be showing $37 in the 11am hour. This represents the espresso in the first order, and then the second order for the latte and BLT in this period.

Update an order over time

The first two orders were pretty straight forward, there wasn't any status changing required or things like that. Now we're going to show the requests that are sent for an interaction that represents what happens during table service.

In this example we'll assume a customer sits down and orders two Cola's and a House Lager from Jane Doe, they're not asked to pay immediately. The customer then orders the steak, the fish, and two fruit salads for dessert. Finally after they've enjoyed their meal they pay - splitting the bill.

Order some drinks

We start off by creating our order for the drinks. Here's the JSON for that:

{
"externalId": "my-order-id-3",
"createdAt": "2023-07-02T18:45:00Z",
"status": "Created",
"staffMemberExternalId": "jane-doe-id"
"items": [
{
"externalId": "my-cola-item-id",
"requestedTime": "2023-07-02T18:45:00Z",
"quantity": 2,
"unitPrice": 4,
"unitTax": 0.52,
},
{
"externalId": "my-lager-item-id",
"requestedTime": "2023-07-02T18:45:00Z",
"quantity": 1,
"unitPrice": 10,
"unitTax": 1.3
}
]
}

Notice how the status value is different this time, it's Created to represent that the order has been created but it's not yet in a final state. There is also no tender information, this is because nothing has been paid for.

We send that off to start the order:

curl \
-X POST \
-d '{ "externalId": "my-order-id-3", "createdAt": "2023-07-02T18:45:00Z", "status": "Created", "staffMemberExternalId": "jane-doe-id" "items": [ { "externalId": "my-cola-item-id", "requestedTime": "2023-07-02T18:45:00Z", "quantity": 2, "unitPrice": 4, "unitTax": 0.52, }, { "externalId": "my-lager-item-id", "requestedTime": "2023-07-02T18:45:00Z", "quantity": 1, "unitPrice": 10, "unitTax": 1.3 } ] }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/orders
info

In Loaded the Orders report will now be showing $18 in the 6pm hour. This represents the two colas, and the beer ordered in this time period. The Sales report shows nothing for the same time period - this is because the customer hasn't yet paid for anything so no sale has actually occurred.

Order main meals and dessert

We now need to place the order for the meals and desserts. This time we are going to be sending a PATCH request to the /pos/orders endpoint, updating the existing order by adding more items to it.

The JSON we're going to send in our PATCH request looks like:

{
"items": [
null,
null,
{
"externalId": "my-steak-item-id",
"requestedTime": "2023-07-02T18:55:00Z",
"quantity": 1,
"unitPrice": 40,
"unitTax": 5.22,
},
{
"externalId": "my-fish-item-id",
"requestedTime": "2023-07-02T18:55:00Z",
"quantity": 1,
"unitPrice": 45,
"unitTax": 5.87
},
{
"externalId": "my-fruit-item-id",
"requestedTime": "2023-07-02T18:55:00Z",
"quantity": 2,
"unitPrice": 15,
"unitTax": 1.96
},
]
}
caution

The PATCH approach for items has a slight quirk, we want to update the Order to have three new items added to it without having to supply the original two items again (as we don't want to change them in any way). To support this the API requires you to send null objects through in the position of the items array representing those first two (sent in the previous request).

Think of the items array as a list, the API will update based on the position in the list.

Be careful not to overwrite earlier data when sending PATCH requests!

Send off the update to the order using the external id of the order in the PATCH request endpoint /pos/orders/eid:my-order-id-3:

curl \
-X PATCH \
-d '{ "items": [ null, null, { "externalId": "my-steak-item-id", "requestedTime": "2023-07-02T18:55:00Z", "quantity": 1, "unitPrice": 40, "unitTax": 5.22, }, { "externalId": "my-fish-item-id", "requestedTime": "2023-07-02T18:55:00Z", "quantity": 1, "unitPrice": 45, "unitTax": 5.87 }, { "externalId": "my-fruit-item-id", "requestedTime": "2023-07-02T18:55:00Z", "quantity": 2, "unitPrice": 15, "unitTax": 1.96 }, ] }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/orders/eid:my-order-id-3
info

In Loaded the Orders report will now be showing $133 in the 6pm hour. This increase comes from the two main meals, and the desserts being ordered in this period. There are still no Sales numbers showing as payment hasn't been received.

Pay for the order by splitting the bill

We're now going to finalise this order by processing payment for it. Lets pretend that the customer has asked to split the bill, the drinks will be paid for in cash and the meal on debit card.

We're going to run another PATCH to the order to achieve this. We'll be adding the tender information, and also shifting the status of the order and items to their final statuses.

Here's the JSON we're going to send in the PATCH request:

{
"completedAt": "2023-07-02T19:35:00Z",
"status": "Completed",
"items": [
{
"settlementStatus": "Paid"
},
{
"settlementStatus": "Paid"
},
{
"settlementStatus": "Paid"
},
{
"settlementStatus": "Paid"
},
{
"settlementStatus": "Paid"
},
],
"tenders": [
{
"externalId": "my-tender-id-3",
"tenderedAt": "2023-07-02T19:35:00Z",
"type": "Cash",
"invoiceAmount": 18
},
{
"externalId": "my-tender-id-4",
"tenderedAt": "2023-07-02T19:36:00Z",
"type": "DebitCard",
"invoiceAmount": 115
}
]
}

Similar to adding the additional items in the previous request, we're sending a PATCH to update the order again:

curl \
-X PATCH \
-d '{ "completedAt": "2023-07-02T19:35:00Z", "status": "Completed", "items": [ { "settlementStatus": "Paid" }, { "settlementStatus": "Paid" }, { "settlementStatus": "Paid" }, { "settlementStatus": "Paid" }, { "settlementStatus": "Paid" }, ], "tenders": [ { "externalId": "my-tender-id-3", "tenderedAt": "2023-07-02T19:35:00Z", "type": "Cash", "invoiceAmount": 18 }, { "externalId": "my-tender-id-4", "tenderedAt": "2023-07-02T19:36:00Z", "type": "DebitCard", "invoiceAmount": 115 } ] }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/orders/eid:my-order-id-3
info

In Loaded the Sales report will now be showing $133 in the 7pm hour. The payments were processed during that hour and Loaded is showing when payment was received to the user. The Orders report will remain showing the $133 in the 6pm hour as it is showing the time the order was placed.

Track an order that was wasted

We're now going to process an order for a granola bowl that ended up being dropped on the way to the customer. This information is still very useful to Loaded - the ingredients in that dish were used up and ended up costing the business money, Loaded's stocktaking and profitability reports take wastage into consideration.

The JSON for tracking a voided item is very similar to the first Order we processed. However instead of marking the item settlementStatus as Paid we're going to use the VoidWithWastage status. In this example we're processing a separate Order just for the wastage, so there won't be any Tender. There's nothing to stop you voiding particular items in an Order though.

{
"externalId": "my-order-id-4",
"createdAt": "2023-07-02T13:00:00Z",
"completedAt": "2023-07-02T13:00:00Z",
"status": "Completed",
"staffMemberExternalId": "jane-doe-id"
"items": [
{
"externalId": "my-granola-item-id",
"requestedTime": "2023-07-02T13:00:00Z",
"quantity": 1,
"unitPrice": 15,
"unitTax": 1.96,
"settlementStatus": "VoidWithWastage"
}
]
}

We send this Order off in the usual way via a POST request to the /pos/orders endpoint:

curl \
-X POST \
-d '{ "externalId": "my-order-id-4", "createdAt": "2023-07-02T13:00:00Z", "completedAt": "2023-07-02T13:00:00Z", "status": "Completed", "staffMemberExternalId": "jane-doe-id" "items": [ { "externalId": "my-granola-item-id", "requestedTime": "2023-07-02T13:00:00Z", "quantity": 1, "unitPrice": 15, "unitTax": 1.96, "settlementStatus": "VoidWithWastage" } ] }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/orders
info

The Loaded Orders report will now be showing $15 in the 1pm hour, there will also be $15 showing in the Voids report for the same period.

Refund an order

Finally we're going to process a refund for the first order we created, the espresso. As you might have guessed this is pretty similar to the other requests related to Orders. However one difference is that we always process refunds as separate Orders. It's not possible to update an existing order to a refunded status.

Our refund order to give money back to the customer for their espresso has JSON that looks like the following:

{
"externalId": "refund:my-order-id-1",
"createdAt": "2023-07-02T20:10:00Z",
"completedAt": "2023-07-02T20:10:00Z",
"status": "Refunded",
"staffMemberExternalId": "jane-doe-id"
"items": [
{
"externalId": "my-espresso-item-id",
"requestedTime": "2023-07-02T11:30:00Z",
"quantity": 1,
"unitPrice": 5,
"unitTax": 0.65,
"settlementStatus": "Refunded"
}
],
"tenders": [
{
"externalId": "my-tender-id-5",
"tenderedAt": "2023-07-02T20:10:00Z",
"type": "Cash",
"invoiceAmount": -5
}
]
}
tip

For refunds the invoiceAmount for the Tender is a negative value to represent the tender is money returning to the customer.

We send off the refund order as per usual:

curl \
-X POST \
-d '{ "externalId": "refund:my-order-id-1", "createdAt": "2023-07-02T20:10:00Z", "completedAt": "2023-07-02T20:10:00Z", "status": "Refunded", "staffMemberExternalId": "jane-doe-id" "items": [ { "externalId": "my-espresso-item-id", "requestedTime": "2023-07-02T11:30:00Z", "quantity": 1, "unitPrice": 5, "unitTax": 0.65, "settlementStatus": "Refunded" } ], "tenders": [ { "externalId": "my-tender-id-5", "tenderedAt": "2023-07-02T20:10:00Z", "type": "Cash", "invoiceAmount": -5 } ] }' \
-H "Content-Type: application/json" \
-H '"Authorization=Bearer {token}"' \
https://api.loadedreports.com/v1/pos/orders
info

With this refund processed the Loaded Orders and Sales reports for the 11am hour will still be showing $37. However the 8pm Sales report will be showing -$5 now to reflect that the refund transaction occurred at that time.