Run a day of deliveries

From first sign-in to a reconciled cash shift. Written for the person in the dispatcher seat.

Open the console

Getting started

You need a browser for the dispatcher console and, for each courier, a phone with the courier app. Store builds of the app are not published yet.

  1. 1

    Open the console

    Use the Open live demo button or go to the console address your deployment uses.

  2. 2

    Sign up or sign in

    A service signs itself up: name, phone, first warehouse and your email. A sign-in link arrives by email and works for 15 minutes. Whoever signs the service up becomes its owner.

  3. 3

    Read the map

    Each courier has one line colour everywhere: on the map, in lists and in plans. A short label beside the name shows whether they are on shift, on break or off shift.

Team and roles

A service has three roles. The owner runs the company: team, warehouses, the recipient page and the plan. The dispatcher runs the day. The courier works in the app. One person can belong to several services and switch between them.

  1. 1

    Invite people

    Open Company, then Team, and press Invite. Choose a role and enter a name. The console gives you a link to copy. If you add an email address, the link is emailed too.

  2. 2

    Hand over the app

    The courier opens the link on their phone. The app accepts the invitation, shows the service name, and explains why location is needed before the phone asks for permission.

  3. 3

    Disable when needed

    A disabled member cannot sign in, and a disabled courier cannot be assigned orders. A courier who lost access can get a new sign-in link from the same menu.

Create an order with a pin

The pin is what routing uses. The address text is for people.

  1. 1

    Start a new order

    Enter the recipient’s name and phone number.

  2. 2

    Place the pin

    Click the map where the parcel goes. Pins must sit inside Armenia; the API refuses coordinates outside it.

  3. 3

    Label the address

    Armenian is required. Russian and English are optional but make the courier and tracking screens read naturally in each language.

  4. 4

    Add cash or a code

    For cash on delivery, switch it on and set the amount in AMD. To require a one-time delivery code, switch that on; the recipient reads it from their tracking link.

  5. 5

    Save and mark ready

    An order moves draft, ready, assigned, picked up, arrived, delivered. A failed delivery returns to the dispatcher, who can put it back in the queue.

Assign or optimise

Assign by hand for one order, or ask for a plan for many.

  1. 1

    Assign one order

    Pick a ready order and an active courier. Reassigning cancels the previous assignment and records both events.

  2. 2

    Request a plan

    Select orders and couriers and ask the optimiser for a suggestion. It proposes a sequence of stops per courier.

  3. 3

    Review and edit

    The suggestion is not guaranteed optimal. Move stops between couriers, change the order, re-optimise what is left.

  4. 4

    Apply once

    Applying assigns every stop in the accepted sequence or changes nothing. If an order moved on while you were reviewing, the plan is refused as stale.

Share a tracking link

Give the recipient a page of their own, with nothing they should not see.

  1. 1

    Create the link

    Open the order and copy its tracking link. Send it by any channel you already use.

  2. 2

    What they see

    Status, ETA, a coarse courier position, the time of the last update and, if required, the delivery code to read to the courier.

  3. 3

    What they never see

    Other stops, route history or an internal order number. The courier’s phone shows only if the owner turns it on in the recipient page settings.

  4. 4

    Revoke at any time

    Revoking takes effect immediately. A new link replaces the old one. Links also expire after delivery.

Courier app basics

What to tell a courier on their first morning.

  1. 1

    Start the shift

    Tap start on the shift card. Location is only collected on shift; break pauses it and end stops it.

  2. 2

    Work the run

    Stops are listed in the planned order. Tap one to see where to go and open navigation in one tap.

  3. 3

    Mark progress

    Picked up, arrived, then delivered. If delivery fails, choose a reason: recipient absent, refused, wrong address or other.

  4. 4

    Record proof

    Take a photo, enter who received the parcel, or ask for the one-time code when the order requires it.

  5. 5

    Lose signal safely

    Changes wait on the phone and send automatically when signal returns. The status bar shows how many are queued.

Cash on delivery and reconciliation

Cash is counted at the door and settled at the end of the shift.

  1. 1

    Collect at the door

    On a cash order the app shows the amount due and prefills what was collected, with change worked out.

  2. 2

    Track what is held

    The courier’s home screen shows a running total still to hand over. The dispatcher sees the same figure per courier.

  3. 3

    Hand over

    At the end of the shift the courier taps hand over cash. The balance shows as awaiting confirmation.

  4. 4

    Confirm receipt

    The dispatcher confirms in the cash reconciliation panel. The balance returns to zero.

API overview

Everything the console and the apps do goes through one HTTP API. Requests carry a bearer token from POST /auth/login or a sign-in link; refresh tokens rotate on use. Every request works within the user’s active company. Errors are small JSON problem objects with a type, title and status.

AreaMain endpoints
Authentication/auth/signup, /auth/login, /auth/magic-link, /auth/refresh, /auth/logout, /auth/switch-company, /me
Company and team/company, /company/depots, /company/members, /company/invites, /company/billing, /auth/invite/accept
Orders/orders, /orders/{id}, /orders/{id}/status, /orders/{id}/events, /orders/{id}/notify-late
Assignment and plans/orders/{id}/assign, /plans/recompute, /plans/move-stop, /plans/apply, /geo/optimize
Couriers/couriers, /couriers/{id}, /couriers/{id}/eta, /courier/me, /courier/shift/start|break|end
Courier work/courier/orders, /courier/orders/{id}/status, /courier/location
Cash and earnings/courier/cash, /cash/settlements, /courier/earnings, /courier/history
Recipient tracking/orders/{id}/tracking, /track/{token}, /track/{token}/rating
Live events/events (server-sent events), /events/latest-cursor
Geo/geo/route, /geo/matrix, /geo/optimize, /healthz

Geo endpoints are for signed-in dispatchers and couriers only; the public tracking page computes its own ETA on the server.

OpenAPI document (JSON)

Running it yourself

One deployment serves many services. Each sees only its own orders, couriers and settings.

  1. 1

    Check health

    GET /healthz answers 200 when routing, optimisation, the database and tiles are up, and 503 with the failing part named when they are not.

  2. 2

    Keep the map fresh

    Refresh OpenStreetMap data weekly; one command downloads, rebuilds the routing graph and smoke-tests a route.

  3. 3

    Back up and drill

    Nightly database backups are verified when written. Run the restore drill after schema changes and monthly.

  4. 4

    Set retention

    Location history and dead tracking tokens are pruned on a schedule. The defaults are placeholders until counsel sets the real periods.

The full runbook is OPERATIONS.md in the repository.