docs
/
Courses — AppEngine

AppEngine Logistics and Space Booking APIs

Watch on YouTube ↗

Video chapters
  1. AppEngine Logistics, Rental and Storage APIs
  2. Three journeys, different rules
  3. Accounts, configuration and documentation
  4. Open the prerequisites and current API reference
  5. What the rental service owns
  6. Create equipment and pricing
  7. Quote, reserve and handle unavailable stock
  8. Charge, record and refund
  9. Pay the rental and take the deposit
  10. Hand over and record the return
  11. Refund the deposit and release stock
  12. Cancel separately from refunding
  13. Quote, cart, hold and booking
  14. Host eligibility, space and units
  15. Save the cart and hold capacity
  16. Pay, confirm and safely retry
  17. Extend the paid stay
  18. Movement is different from checkout
  19. Check in each box
  20. Release one box and close its stay
  21. Finish collection and reconcile the payment
  22. Preview cancellation and verify the refund
  23. Dispatcher and driver responsibilities
  24. Register, approve and go online
  25. Validate the route and create the job
  26. Offer and accept
  27. Record pickup
  28. Record delivery proof
  29. Complete once and inspect earnings
  30. Build recovery around the saved record
  31. Your client, AppEngine business operations

Written guide

Build an equipment-rental desk, a customer and host storage application, and a dispatcher and driver client on AppEngine. The worked example uses Harbour Moves: Dana rents two hand trucks, stores two boxes, then Sam delivers the boxes. These are actual saved AppEngine records in an isolated development organization. Card operations use Stripe TEST; the physical delivery is simulated. No external payout is requested.

Video recording and independent review are in progress. This reader distinguishes verified behavior from remaining production work.

1. Start with the platform and the right identities

Open Appmint Studio and your development organization. Use the organization's assigned AppEngine backend address and organization ID; the Studio website is not automatically your API origin. Keep the maintained API reference open beside the companion source.

API Foundations demonstrates organization setup at 0:50, customer signup at 1:51, sign-in and returned challenges at 2:26, and staff versus customer identity at 7:11. Complete any verification or temporary-password challenge before continuing. API Reference explains deployment at 0:54, the caller at 1:25, and endpoint lookup at 2:35. Headless Storefront Development provides the payment-gateway setup and customer card experience; this course uses those prerequisites to teach rental and storage operations.

Prepare four separate identities in the same development organization:

IdentityPurposeAccount and eligibility
Operations staffConfigure equipment, collect authorized payments, approve drivers and dispatch jobsStaff sign-in with the permissions required by those routes
DanaQuote, hold, pay for and inspect her storage bookingsCustomer sign-in
Alex, storage hostOwn a listing, receive and release items, inspect and refund owned paymentsCustomer sign-in plus approved stowbo-host eligibility
Sam, driverRegister, accept offers, collect and deliverCustomer sign-in plus an approved delivery-agent profile

A host or driver remains a customer identity. Changing the label in your app does not give a token another role. Do not place a staff token in a public customer or driver application. The multi-role companion is a development workbench; real applications should connect only their appropriate identity and keep secrets in their intended server or session boundary.

Requests use the assigned backend, orgid, and the caller's bearer token. The following sections focus on the platform decisions, not repeating the same request syntax. The TypeScript, Python, Flutter and HTTP companion files show the concrete calls.

Staff, customer, host and driver identity boundaries
Concept illustration. Host and driver eligibility extends a customer account; it does not supply staff authority.

2. Understand the three lifecycles

With rental, the business's equipment goes out and returns. Availability depends on the equipment, quantity and date window. With storage, the customer's belongings arrive, occupy space and eventually leave. Each item has its own custody history. With delivery, a driver accepts a job and records pickup and dropoff proof.

Keep their identifiers and states separate. A rental number is not a delivery-job number. A storage booking is an order, while its booking items represent individual boxes. A delivered job is not automatically a completed earnings settlement. One application can connect these records while preserving what each operation means.

The built-in records include sf_rental_item and sf_rental, stowbo_listing, stowbo_unit, stowbo_booking, stowbo_booking_item and checkout holds, plus delivery_agent, delivery_job, zones and configuration. Use module operations to change business state. Generic Repository writes are appropriate for configuration records where the documented setup uses them; they are not a substitute for checkout, refund or delivery completion.

Rental equipment, stored belongings and delivered boxes
Concept illustration. Physical custody and each module’s state remain separate, including partial collection.

3. Configure the equipment, then ask for price and availability

In the companion's Equipment rental view, add a rental item. Give it a unique SKU, a human name, active status, available quantity 2, a daily price of 15 USD, and a fixed refundable deposit of 20 USD. Saving creates an sf_rental_item record. The example uses the supported Repository create operation with datatype, isNew and data; the full request is in the companion. An existing item can instead be configured in Appmint's Rental Items interface.

The equipment client after saving its rental item

Actual client capture. The SKU identifies the item used by the pricing and availability operations; it is not the later rental number.

Choose a start and end, then ask GET /storefront/rental/items/:sku/availability with the ISO date window and quantity. Ask POST /storefront/rental/items/:sku/price for the same inputs. Display the returned currency, base period, duration, fees, tax, total and deposit.

Two hand trucks at $15 per day for two days produce a $60 rental fee. The fixed $20 deposit applies to the rental; it is not multiplied by quantity in the current calculation. The result is authoritative. Do not calculate a different browser total or treat the refundable deposit as rental income.

Date inputs need deliberate conversion. HTML datetime-local values are local wall time; convert them once to an ISO instant for the request, and convert the stored instant back to local display. Reusing a sliced UTC string as a local input repeatedly shifts the time. The companion converts local input to an ISO instant once and converts the returned instant back for display.

The rental service also evaluates minimum and maximum duration, blocked dates and buffer time. Customer restrictions are checked when creating the reservation. Use the maintained Rental reference to configure the rules your equipment needs. An availability read is not a reservation: another operation may consume stock before creation, so handle a rejected create and let the customer choose a different quantity or date.

4. Create the reservation and verify stock consumption

Create through POST /storefront/rental with the SKU, quantity, dates, customer details and fulfillment/return choices. For this example the customer collects and drops off the equipment. Delivery fulfillment can instead carry an address and instructions; it remains a rental fulfillment choice, not an automatically assigned driver job.

Keep data.name, the returned rental number, for subsequent rental routes. The created record starts pending. Read availability again for the same window. The rehearsal reserved both hand trucks and then observed zero remaining stock; another overlapping reservation returned 409. Show that error beside the customer's selected dates, keeping their inputs intact.

Confirm the reservation with its confirm operation. Confirmation, payment, deposit collection and physical handover are distinct decisions. Your UI should expose the actions appropriate to the current saved state and disable a button while its request is pending.

Second overlapping rental is rejected
Actual AppEngine-backed client. Both hand trucks are already reserved for these dates; the second create does not silently overbook.

5. Charge a card, then record the rental payment and deposit correctly

The rental payment endpoint records money already collected. It does not itself charge a card. In this developer example:

  1. The staff payment operation charges the configured Stripe TEST gateway. Finance amounts use minor units: $60 is 6000 cents.
  2. Require a successful provider result. The rehearsal additionally checked the returned Stripe object had livemode: false.
  3. Send the successful reference to POST /storefront/rental/:rentalNumber/payment, with the rental amount in major units, method and original gateway. The rental now shows paid.
  4. Collect the $20 deposit separately through the test gateway, then call PUT /storefront/rental/:rentalNumber/deposit/hold with its original transactionId, paymentGateway and method.
  5. Reload the rental and check that the fee is paid and the deposit is held.

Do not call a record-payment operation to invent a cash receipt. For a real counter payment, record it only after cash or a terminal payment was received. The deposit hold likewise records the collected source; it is not the same as a card authorization followed by a later capture. The Finance course covers that separate authorization lifecycle.

The companion's pm_card_visa path is an explicitly gated Stripe TEST demonstration. A production web or mobile application obtains the customer's real payment-method identifier through the provider's supported UI and follows the documented verification flow. Never use a server secret key in a browser or mobile bundle. Link to Headless Storefront for the full provider UI instead of copying the test helper into production.

Rental payment and deposit recorded separately
Actual TEST payment result. Fee payment and deposit hold have separate original provider references.

6. Hand over, return, refund and complete the rental

Use PUT /storefront/rental/:rentalNumber/checkout when the equipment is actually handed over. Record condition, the staff member checking it, notes and any file references for photographs. This makes the rental active. The Files course explains uploading evidence and retaining its returned references; a local filename is not an uploaded proof photo.

On return, call the check-in operation with the returned condition and any damage information. The record becomes returned. The service evaluates applicable late-return fees from the item or configuration. Inspect the updated calculation rather than assuming an on-time amount after a late return.

For undamaged equipment, refund the held deposit through the deposit-refund operation. Its original gateway reference lets the service return the money through Stripe or PayPal instead of merely changing a badge. A deduction changes the amount available to refund; inspect the remaining refundable amount and reason before submitting it. Do not use a gateway-skip flag for a card deposit.

Complete the rental, reload it, and ask availability again. In the verified rehearsal the saved deposit read refunded, the rental read completed, and both hand trucks were available. The current availability query still counts returned rentals until completion, so keep the final completion step in your client.

Completed rental and released stock
Actual saved result. The deposit refund and completion precede the fresh availability read.

7. Cancellation is not a refund

Use a separate reservation to demonstrate a customer's changed plan. Pay it through the test gateway, then cancel it with a reason. The saved reservation can be cancelled while its payment still reads paid. Refund the payment explicitly using the original source, then reload the record.

The current rental cancellation contract can request staff-authorized deposit/payment refunds, but does not refund by default. A refund can also be partial. The payment-refund operation validates that the amount is positive and no more than the unrefunded balance. For a manual cash or terminal payment, the service requires confirmation that money was actually returned; do not assert that for a card transaction. Keep the returned provider reference and refund history visible to operations.

An active, returned or completed rental cannot be treated as a never-started cancellation. Follow its return/settlement path. For changed dates, check the current Rental reference for the supported workflow; never patch a date and leave a stale price or overlapping availability behind.

Cancelled reservation with refunded payment
Actual separate reservation. Cancellation and the rental payment refund were performed as distinct operations.

8. Become a storage host and configure the space

In the storage host application, inspect the host application definition and current eligibility. Submit POST /client/stowbo/host/apply with the actual form data and accepted agreement. The development organization's default policy approved the controlled application; other organizations may require staff review. Read host/me and wait for its approved result rather than assuming every application is immediately accepted.

Create a host-owned listing through POST /client/stowbo/host/listings. Our listing has capacity two, numbered units A1 and A2, a per-day rate of $5 for each unit and 100% upfront payment. Use the current rates.bands shape; the legacy price/priceUnit fallback exists for older records. Configure the host's access, location, availability and cancellation policy as needed before opening a real listing.

Keep two identities: the listing's record sk for owner-management routes, and its generated data.name code for line items, units and availability. Create the numbered units against that listing code, then set the listing active. A title is for people and must not be used as a guessed unique identifier.

Storage also supports listing hierarchies: booking a whole parent space can block its child spaces, and an occupied child can prevent selling the whole parent. Numbered-unit availability and configured blackouts further affect what is bookable. Ask the platform's availability and quote operations instead of relying only on the capacity number shown on a listing.

Host listing and units after setup
Actual host application and listing setup. This organization’s policy approved this training host; do not assume every deployment auto-approves.

9. Quote, save the cart, hold space and pay

Build the customer's request from the selected listing code, quantity two, and the start/end instants. Quote it with POST /client/stowbo/checkout/quote. The week-long example totals $70.

A saved checkout cart preserves the selection and can be resumed. It does not hold capacity. Create a checkout hold and retain its checkoutId, expiresAt, quoted totals and due-now amount. Display the expiry. If the hold expires or space becomes unavailable, re-quote and create a new valid hold; do not repeatedly submit an expired identifier.

Confirm using that checkout ID. The rehearsal first omitted payment and received 402 PAYMENT_REQUIRED, without a completed booking. With the configured Stripe TEST payment method, confirmation succeeded and the saved summary showed $70 paid and zero balance. The provider verification confirmed livemode:false.

On an interrupted response, retry the same confirmation. The rehearsal returned the same booking ID rather than a second order or second payment. This is different from starting another checkout. A mobile client can use the documented confirmed payment-intent path, whose amount and state are checked by the server. Keep the payment state, hold state and saved booking result distinct in the UI.

Paid booking and two reserved custody records
Actual confirmation readback. Retrying the same checkout returns the same booking; each box has a separate saved item record.

10. Extend the stay and handle failed changes

The extension operation takes the proposed end date and selected line. It checks the additional time, recalculates the price and collects any additional payment before saving the new window. Read the changed booking and payment summary after success. A declined payment or unavailable extra interval must not be presented as an extended stay.

For cancellation, ask the booking's due endpoint with action=cancel first and show its result. Then submit the cancel operation with a reason if the customer chooses it. Current custody affects whether cancellation is allowed: a booking whose belongings have already been handed over needs the collection/checkout path. The cancellation calculation can incorporate policy, collected payment and refund eligibility; a fixed client-side “full refund” message is not sufficient.

The recorded example extends both boxes by one day. AppEngine collects an additional $10 in Stripe TEST, saves the later end date and returns $80 total, $80 paid and zero balance. A fresh booking read shows the same result. The client retains the booking ID: an extension response can be a summary rather than the full booking record.

Saved storage extension: $80 total, $80 paid, zero balance

Actual saved extension and payment summary. The original $70 payment and additional $10 payment remain distinct transaction references.

For the separate cancellation demonstration, two boxes were booked but had not arrived. The actual preview returned $70 refundable and no cancellation fee. Applying cancellation saved a cancelled booking and $0 total, $0 paid and $0 balance. The $70 quote remains the original quote, while the saved money summary shows the cancelled outcome.

Cancelled pre-arrival booking with zero remaining balance

Actual policy-based cancellation and saved money readback. This differs from refunding an otherwise completed stay.

11. Track custody per box, not just per order

Load the booking's items in the host view. The verified booking produced two separate stowbo_booking_item records. Check Box 1 into A1 with identifier DANA-BOX-1, then Box 2 into A2 with DANA-BOX-2. Check-in creates the initial inbound movement and records arrival. The pickup code belongs to the booking and can support the documented handover workflow.

A unit assignment tells you where an item belongs. A movement records an item going in or out; repeated movements do not create a new paid stay each time. The host's resolve endpoint can locate a booking from a scanned/read identifier, phone, unit, box or reference. This is the appropriate place to connect a barcode scanner that enters its decoded value; do not make the device call an unrelated payment-card interface.

Attempting checkout while Box 1 remained present returned 409 STILL_PRESENT in the rehearsal. Record the outbound movement to Sam, inspect the item's checkout statement, and then close that stay. The statement identifies final usage or overstay and whether the item can close. The order remained active because Box 2 was still stored. Releasing and checking out Box 2 completed the order.

A handover can include photos, signature, identification and the collector's details through the documented handover/movement routes. Keep sensitive proof references in the appropriate access boundary. Do not fabricate an uploaded image or signature merely to make a successful response look more complete.

First box ended, second box still active

Actual first collection. The saved checkout statement belongs to the ended first stay; the second box remains inside.

12. Refund the storage payment without erasing the stay

A bill credit and a gateway refund are different operations. A host can adjust a bill using the documented charge/credit/line-reversal operations. To send a collected payment back through its provider, use the owned transaction's refund operation with the original gateway reference and, for a partial refund, the requested amount.

The recorded example refunded both its original $70 TEST payment and its $10 extension payment. The saved booking remained completed, while the payment summary changed to $80 total, $0 paid and $80 balance. The provider refund returned the collected test money; it did not credit or cancel the bill. The operation preserved the booking and custody history. Inspect both the booking's money summary and the owned transaction ledger after a refund. Refunding can leave a booking with a balance according to its remaining bill; it does not silently rewrite the physical collection history or cancel a completed order.

Completed storage order after the original and extension TEST refunds

Actual completion and money readback. $80 balance remains because refunding collected money does not erase the $80 bill.

Host available funds are derived from the confirmed transaction ledger. This training host has no live payout destination and the course does not request or send a payout. The Finance course handles payout destinations, approvals and sending as a separate sequence.

13. Register a driver, dispatch the job and prove delivery

Sam signs in as a customer and submits driver registration with the vehicle details. Staff approves the resulting delivery-agent profile. Sam then sets availability online. This is separate from owning a customer account. The dedicated training driver had zero payout destinations before the demonstration.

Sam registered, approved and online

Actual customer driver registration followed by staff approval and customer availability.

Build ordered pickup and dropoff stops with coordinates or valid addresses, appropriate contact data and items. Request a validated delivery quote. The rehearsal used public Chicago locations and the runtime returned Google as its route source. Routing providers and platform metering depend on deployment configuration; do not describe a schematic line as a measured road route or assume a browser-supplied distance is authoritative.

Validated route and saved delivery job

The actual quote identifies Google as its route provider, $15 customer price and $11.25 driver earnings. These are quote values; the earnings ledger remains pending.

Create the job with requireSystemQuote:true. AppEngine validates the system quote again. Retain the returned job number. Offer it to the intended agent, then have that driver accept with their own session. Broadcast offers and direct assignment are alternatives with different dispatch policies; use the maintained Delivery reference for their filters and eligibility rather than assuming every online driver received an offer.

Follow the driver's actions continuously: start pickup, arrive at pickup, complete pickup with its stop index and proof; start dropoff, arrive, complete dropoff with the destination index and proof. The demonstration records actual state transitions while simulating the physical journey. Both stops retain their own proof notes. The job becomes delivered when all dropoffs are complete.

Complete the job as a separate operation. In the verified rehearsal this recorded $11.25 of training earnings and completed the job. Repeating completion left exactly one linked earning transaction. Source review confirmed this path wrote the internal training ledger and notifications without making an external provider transfer. No payout was requested and the balance was not spent.

For a problem on the road, use the documented issue/message and job tracking operations. Inspect the assigned job and its current stop before retrying. Do not create a replacement job just because an app lost its last response, or mark a job complete through a Repository status update that skips proof and earnings behavior.

Both delivery stops completed with saved proof; job delivered

Actual saved pickup and dropoff notes. Delivered still precedes the separate earnings completion operation.

Completed driver job and one credited training earning

Recorded completion and repeat/readback preserved $11.25. An independent ledger read found exactly one earning entry for this recorded job and zero payout destinations. No payout operation ran.

14. Build the production client around maintained contracts

Open the companion source and README on GitHub for environment variables, session setup and run commands. Open the browser client source, TypeScript client, Python runner, Flutter client, and operation manifest.

The companion retains the operations and examples in JavaScript/TypeScript, Python, Flutter and HTTP form. Use it to reproduce the controlled workflow, then adapt its presentation and identity handling. Connect only the appropriate account in a deployed app. Keep pending states visible, preserve customer input after a rejected operation, and reload the saved resource before displaying completion.

CapabilityMaintained referenceWhat the client must preserve
EquipmentRentalSKU versus rental number, returned price, quantity/date rules, original payment source
Storage customer and hostStowbo ClientListing code versus record ID, checkout expiry, payment result, individual custody records
DispatchDeliveryValidated stops, serviceable zones, offer/assignment, job identity
Driver appLogistics ClientDriver session, ordered stop actions, proof and completion
Money movementFinance courseCharge/record distinction, minor versus major units, refund source, separate payout lifecycle

Use the API reference's current operation details when adding fees, restrictions, add-ons, cancellation policies, open/metered stays, delegated pickup, driver issues, tracking or reconciliation. These are extensions of the same lifecycles. Do not guess a payload from an old video frame.

Verification and production status

Current source review covers the Rental controller/service, Stowbo client/core/pricing/configuration/notification services, Delivery staff/client/service, and Finance payment/payout behavior. Saved rehearsal evidence is in the course's production lab. Verified outcomes include reservation capacity rejection, paid TEST rental/deposit/refund, completed rental stock release, storage payment-required rejection and idempotent confirmation, per-box custody and collection, storage TEST refund, and driver completion with exactly one internal training earning.

The actual captures above are checked against saved AppEngine results. All described core operations have actual captured results, including both storage collections, policy cancellation, refunds and driver completion. Final narrative timing and encoded visual/audio review are still in production. The film is not marked ready for review yet. The companion source is published at commit 878a282; React production build, Flutter analysis, TypeScript compilation and portable request checks passed.