Dashboard
Quotes & invoices
Loading…
Also needs you
Loading…
Next flights
All flightsLoading…
Colours Shop weights
Loading…
Revenue
This monthLoading…
Invoices & Quotes
All documents across bookings and orders -- view, reprint, or resend
Loading...
Drop-ship Intake
Pre-register a drop-ship merchant's packages before they physically arrive - one sender, many receivers - paste a manifest, get an order with one tracking code per receiver, ready to confirm on arrival
Paste straight from a spreadsheet, header row included, columns in this order: Order ID, Name, Address, City, State, Zip code, Country, Phone, Email (tab- or comma-separated).
Multi-Package Orders
Orders placed via the multi-package booking form
| Order Ref | Sender | Route | Pkgs | Total | Status | Date | Actions |
|---|---|---|---|---|---|---|---|
| Loading orders... | |||||||
Bookings
All shipment booking requests
| Code | Route | Type | Sender | Receiver | Weight | Amount | Status | Flight | Date | |
|---|---|---|---|---|---|---|---|---|---|---|
| Loading... | ||||||||||
Cancelled orders -- 144h deletion window
Loading...
Payments to check
Review and approve payment uploads
| Booking | Customer | Amount | Files | Status | Submitted | Actions |
|---|
Flights
Manage cargo flight legs
Colours Shop orders on flights
Flown by SAVN on behalf of Colours. Never invoiced. Their weight still counts in the flight forecast above.
Reserved weight for clients
Weight set aside on one flight for a client, by email. The client does not need a SAVN account. It counts against the airline baggage allowance in the forecast until their parcels are booked on that flight, then the real weight replaces it. Costed from the airline baggage prices for that flight's route (23 kg bag price ÷ 23).
Extra baggage planner
Works out the cheapest bags to buy when your total weight goes over what your ticket already includes.
Enter your total weight to see the cheapest bags.
| Option | Bags | Capacity | Cost | Per kg carried |
|---|
Only weight above the included allowance is charged. Whole bags only, so spare capacity is the cost of rounding up.
Airline baggage prices (one tab per route; update when the airline changes them)
Price history
| Changed | Route | What | From | To |
|---|---|---|---|---|
| Loading… | ||||
Quick guide
Cheapest bags by weight over your allowance, using the online 23kg price.
| Excess over allowance | Buy | Cost |
|---|
Quotes
Outstanding quotes — sent but not yet converted to invoices
Loading...
Discounts & Vouchers
Email-assigned discounts, public voucher codes, and who has used them
Email discount: applies automatically to that customer's email in Quick Invoice and at checkout. Voucher code: the customer types it in at checkout. Voucher codes are not used in Quick Invoice.
Codes
Voucher Usage Report
Customer Notes
| Type | Email / Code | % | Min kg | Note | Valid From | Valid Until | Uses | Status | Actions |
|---|
Every time a voucher code is actually used on a completed booking, it shows up here. This is the real usage log -- not the "Uses" count on the Codes tab, which is a running total per code.
| Date | Code | Customer | Discount % | Discount Amount | Booking | |
|---|---|---|---|---|---|---|
| Loading... | ||||||
Informational only. Use this to keep a record of a code you gave someone verbally, or a note about their use of one -- it is never checked at booking time, so it cannot block or approve a discount by itself.
| Added | Code | Note | Added by | Actions | |
|---|---|---|---|---|---|
| Loading... | |||||
Settings
Rates, banking, warehouse and company configuration
Rates
Bank Details
Warehouses
Company
Document Text
Security
Email / SMTP
Customs
Courier Routes
PNR Fares
Push notifications
Versions
Email settings
Every outgoing email (invoices, welcome emails, quotes) is BCC'd to the address below.
SMTP settings
Test your SMTP settings by sending a test email.
Used for password reset emails and booking confirmations. Leave blank to use server default mail().
WhatsApp & Zalo
WhatsApp uses the Twilio WhatsApp Business API. Create a Twilio account at
twilio.com,
enable WhatsApp Sandbox or a verified sender, then enter credentials below.
Zalo uses the Zalo Official Account API -- enter your OA access token below.
reCAPTCHA v3 (optional)
Adds invisible bot protection to the booking form. Get keys at google.com/recaptcha/admin.
Google Places API (optional)
Enables address autocomplete on booking form address fields. Get a key at console.cloud.google.com -- enable Maps JavaScript API + Places API, then restrict the key to your domain.
Admin login
Admin access uses OTP (one-time password) sent to your registered email address. No password is required.
Loading...
Revenue
Revenue, top customers, route performance
Revenue -- ZAR (last 12 weeks)
Loading reports...
Customers
All accounts — search by name, email, phone or Client Number
Loading...
Webhooks
Outbound HTTP notifications
Webhooks fire when a booking status changes. Signed header for verification.
| Name | URL | Status | Actions |
|---|
Audit Log
All admin actions
| Time | Admin | Action | Details |
|---|
Couriers
Manage courier accounts, trips and payment ledger
Courier management is accessed via the Couriers portal at courier.html. Admin invite and rate controls will appear here in a future release.
Routes & Rates
Manage shipping corridors and per-route pricing
| Code | Name | From | To | Order | Active |
|---|
Route Rates (local currency / ZAR)
Flight Schedules
Departure dates and booking cut-offs for each route
| Route | Departure Date | Cut-off (days before) | Notes | Actions |
|---|
Competitor Analysis
Airline excess baggage vs your shipping rate
Global assumptions
Airlines
| Airline | Route | Model | Extra piece - online (USD) | Extra piece - gate (USD) | Overweight surcharge (USD) | Max piece (kg) | Notes |
|---|
Breakeven table - at what rate does your service match each airline?
Cost comparison chart
Support & Amendments
Customer queries and booking amendment requests
| Date | Customer | Booking | Subject | Status | Actions |
|---|
Admin Users
Manage admin accounts and roles
| Username | Display name | Role | Last active | Actions |
|---|
Super -- full access including admin user management |
Dispatcher -- bookings, flights, tracking, warehouses |
Finance -- bookings (read), POP, reports, rates |
Support -- support queries and customer messages only
API Keys
External integration keys for accounting software, CRMs, and custom tools
Keys authenticate via
Authorization: Bearer <key> header.
Base URL: https://thesavietnamshippingcompany.co.za/api/v1/
| Label | Prefix | Scopes | Last used | Expires | Status | Actions |
|---|
Available endpoints
GET /api/v1/bookings.php -- scope: bookings:read -- filter by status, route, date rangeGET /api/v1/customers.php -- scope: customers:read -- search by name, email, phoneGET /api/v1/routes.php -- scope: routes:read -- active routes with current ratesGET /api/v1/reports.php -- scope: reports:read -- revenue by period, route, statusGET /api/v1/errorlog.php -- scope: errorlog:read -- read-only visitor error log feed, for monitoring onlySA deliveries
Admin only. Customers see one line on their booking: Local SA Courier Fee.
Package deliveries
| Package | Receiver | Courier cost | Customer fee | Status |
|---|---|---|---|---|
| Loading… | ||||
Settings
Sender addresses Only shown here. The default is used for booking-time quotes.
Couriers compared
Live booking with Fastway
Booking is currently ?
Quick rate check
Fastway testing tools (raw requests, real bookings, tracking, labels)
Loading...
1. Get a rate quote
Safe to run any time -- never books anything with Fastway. Fill in a real collection and delivery address plus one parcel, then click Get Rate Quote.
Collection address
Delivery address
Parcel
2. Real bookings -- these create an actual shipment in Fastway's system
Fastway will cancel test waybills for us, so this won't be billed -- but it's still real until cancelled. Booking stays switched off until it's turned on here, and switching it back off once you're done testing for the day is recommended.
Live booking is currently: ?
Collection
Delivery
Parcel
Shipments booked so far
| Package | Order | Tracking ref | Status | Booked | Cancelled |
|---|
Finance reports
For your accountant: on screen, with an Excel or PDF download.
Quick periods:
Loading…
WhatsApp log
Invoices and quotes customers asked to have sent to their own WhatsApp from their account page.
| When | Customer | Document | To (last 4 digits) | Status | Detail |
|---|---|---|---|---|---|
| Loading… | |||||
Replies from customers
Customers who wrote back to the sending number. Each one is emailed to you with a button that opens a chat with them on your normal WhatsApp, and they get one automatic message a day pointing to your main WhatsApp.
| When | From | Message | Automatic reply | Emailed to you |
|---|---|---|---|---|
| Loading… | ||||
How it works
On a customer's account page, next to each invoice and on each quote, a WhatsApp button appears (only once this is switched on). They confirm the number, and the same PDF they could download is sent to the WhatsApp number saved on their own account, as an approved WhatsApp template message. Only their own documents, only to their own number (which must include the country code), at most 5 a day, never twice within 90 seconds. Nothing is shown to customers until the set-up below is finished.
Before you start: the number. A number that is already used in a phone's WhatsApp or WhatsApp Business app cannot simply be connected to the Cloud API: Meta's normal route requires deleting that WhatsApp account (its chat history is lost). The cleanest way is a separate number just for sending (a cheap SIM that can receive one SMS or call), with your usual number written in the message so customers know where to reply.
Set-up (once)
On a customer's account page, next to each invoice and on each quote, a WhatsApp button appears (only once this is switched on). They confirm the number, and the same PDF they could download is sent to the WhatsApp number saved on their own account, as an approved WhatsApp template message. Only their own documents, only to their own number (which must include the country code), at most 5 a day, never twice within 90 seconds. Nothing is shown to customers until the set-up below is finished.
Before you start: the number. A number that is already used in a phone's WhatsApp or WhatsApp Business app cannot simply be connected to the Cloud API: Meta's normal route requires deleting that WhatsApp account (its chat history is lost). The cleanest way is a separate number just for sending (a cheap SIM that can receive one SMS or call), with your usual number written in the message so customers know where to reply.
Set-up (once)
- Run
migrations/0091_whatsapp_log.sqlandmigrations/0092_whatsapp_inbound.sqlin phpMyAdmin. - In Meta's developer console create an app with the WhatsApp product, add the sending number to your WhatsApp Business Account, and verify your business.
- Create two Utility templates with a PDF document header, named
savn_invoiceandsavn_quote, with two text variables (first name, document reference). The exact wording is in the upgrade notes. Wait for Meta to approve them. - Create a system user with a permanent access token (permissions: whatsapp_business_messaging and whatsapp_business_management).
- In cPanel File Manager create
whatsapp_credentials.phpin the folder abovepublic_html(never inside it) with your token, phone number ID, app secret and a long random verify token (the template for this file is in the upgrade notes). - In Meta's webhook settings use the callback URL
https://thesavietnamshippingcompany.co.za/api/whatsapp_webhook.php, your verify token, and subscribe to the messages field. This is how delivery results (delivered, read, failed) come back to this page. - Reload this page: the warnings above should be gone. Then send yourself a test invoice from your own account page.
Site health
Every known problem with the site in one list: errors, security, scheduled jobs, backups, email, integrations, installs and SQL. Each line says what to do.
Checking…
Travel inbox
Travel emails sent to chris@ are read automatically and kept here as a diary. Other mail is ignored and never stored.
| Received | Mailbox | What | Details | Booking ref | Status | |
|---|---|---|---|---|---|---|
| Loading… | ||||||
One-time setup
1. Run
2. Upload
3. cPanel > Email Filters > chris@thesavietnamshippingcompany.co.za > Create a filter. Rule: Any Header contains
4. Paste the reader key above (super admin).
A second address (Gmail): in Gmail > Settings > Forwarding, add chris@thesavietnamshippingcompany.co.za, then confirm it with the code Gmail sends there. Then forward only travel mail with a Gmail filter (Create filter, words such as flight OR itinerary OR booking OR hotel, Forward to). The Mailbox column shows which address each email came from.
5. Run
Only emails that mention travel words (flight, itinerary, booking, hotel and so on) are sent to the AI reader. Attachments such as PDF tickets are not read.
1. Run
0121_travel_inbox.sql in phpMyAdmin.2. Upload
travel_mail_in.php and set its permission to 755 in cPanel File Manager.3. cPanel > Email Filters > chris@thesavietnamshippingcompany.co.za > Create a filter. Rule: Any Header contains
@. Action: Pipe to a program, public_html/travel_mail_in.php. Mail still arrives in the inbox as normal.4. Paste the reader key above (super admin).
A second address (Gmail): in Gmail > Settings > Forwarding, add chris@thesavietnamshippingcompany.co.za, then confirm it with the code Gmail sends there. Then forward only travel mail with a Gmail filter (Create filter, words such as flight OR itinerary OR booking OR hotel, Forward to). The Mailbox column shows which address each email came from.
5. Run
0122_travel_inbox_mailbox.sql in phpMyAdmin (adds the Mailbox column).Only emails that mention travel words (flight, itinerary, booking, hotel and so on) are sent to the AI reader. Attachments such as PDF tickets are not read.
Flight diary
How often your flights run late. Each flight in your PNRs is recorded once, after it has landed.
| Flight date | Flight | Route | Airline | Result | Scheduled arrival | Actual arrival |
|---|---|---|---|---|---|---|
| Loading… | ||||||
Waiting to be asked again
None.
How it works
Once a flight in one of your PNRs should have landed, the site asks Aviationstack once for its result and stores it. On time means it arrived within 15 minutes of schedule. A cancelled or diverted flight counts as not on time. A flight that has not finished yet is asked about again 2 hours later, up to 5 times. The free plan allows 100 requests a month and cannot look back more than a day or two, so each flight is asked about soon after it lands. The diary stops by itself at 90 requests a month, and emails you if it has to stop.
Set-up (once)
Once a flight in one of your PNRs should have landed, the site asks Aviationstack once for its result and stores it. On time means it arrived within 15 minutes of schedule. A cancelled or diverted flight counts as not on time. A flight that has not finished yet is asked about again 2 hours later, up to 5 times. The free plan allows 100 requests a month and cannot look back more than a day or two, so each flight is asked about soon after it lands. The diary stops by itself at 90 requests a month, and emails you if it has to stop.
Set-up (once)
- Run
migrations/0090_flight_history.sqlin phpMyAdmin. - In cPanel File Manager, create a file named
aviationstack_credentials.phpin the folder abovepublic_html(never inside it), containing:
<?php
define('AVIATIONSTACK_KEY', 'paste your key here'); - Add a cron job in cPanel (every 2 hours):
15 */2 * * * [PHP path from your cron list, as for the other jobs] cron_flight_history.php (see CRON_SETUP.md)Your daily 8am job also tries once a day as a safety net.
Flight costs
What each flight booking costs per kg of baggage allowance, against what customers pay per kg.
| First departure | Flight and PNRs | Route | Courier | Baggage allowance | Tickets | Stopovers | Full cost | Cost per kg | Customers pay per kg | Margin per kg | Carried (info) |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Loading… | |||||||||||
Cost per kg is always the full cost divided by the baggage allowance (never by the kg actually carried). The full cost is the PNR ticket prices plus every stopover cost (Saigon/Hanoi, Bangkok/Mumbai, Doha/Nairobi, Johannesburg), all in rand. Foreign amounts are converted with the exchange rates the app keeps (updated daily) when the flight is saved, and the rand figure is kept, so a later rate change never alters a past cost. Flights saved before stopovers existed show R 0 stopovers, so their cost per kg is unchanged.
Customers pay per kg is the route's list price. Carried and how full the flight was come from the courier ledger and are for information only.
Customers pay per kg is the route's list price. Carried and how full the flight was come from the courier ledger and are for information only.
Trip model
Route fares, path comparison and saved trip models: cost, revenue, profit and break-even per kg. Saved daily and frozen when the trip is over. Shows profit, so super admins only.
Loading…
Email approvals
Emails wait here for your approval: held emails first, then payment reminders and shipment updates. Nothing below is sent until you press Send. Discard or Dismiss means that email is never sent.
Held emails
Every email the site tried to send, other than invoices, quotes, sign-in codes and mail to you or your team, waits here.
| To | Subject | Held since | ||
|---|---|---|---|---|
| Loading… | ||||
| Customer | Ref | Due since | |||
|---|---|---|---|---|---|
| Loading… | |||||
Email log
Every email the website sends: to whom, when, and whether the mail server accepted it. The message itself is never kept.
| When | To | Subject | Result | Copy to ops | Possibly opened | Clicked | Page opened |
|---|---|---|---|---|---|---|---|
| Loading… | |||||||
Accepted means your mail server handed it to the customer's mail provider; it does not prove it reached the inbox (it may be in junk). Search the mail server ID in cPanel › Track Delivery to see the provider's answer.
Possibly opened is unreliable and is never proof either way: Apple Mail loads the image for everyone, while Hotmail and Outlook block images by default.
Page opened is when the customer opened the invoice or quote from their link (not admins). A visit by a security scanner is shown separately. Entries are kept for 180 days.
Possibly opened is unreliable and is never proof either way: Apple Mail loads the image for everyone, while Hotmail and Outlook block images by default.
Page opened is when the customer opened the invoice or quote from their link (not admins). A visit by a security scanner is shown separately. Entries are kept for 180 days.
Card payments
Lets customers pay an invoice by card. The payment is only counted once PayFast confirms it.
Settings
The fee is added to what the customer pays, so the invoice amount reaches you whole. It is shown to them, with a tick box, before they pay. Take the figures from your PayFast agreement. At 0 and 0 no fee is added.
Setting it up
- Run
migrations/0086_payfast_payments.sqlin phpMyAdmin (once). - In cPanel File Manager, create
payfast_credentials.phpone folder abovepublic_html(not inside it), using the template below. Start with your sandbox details. - Switch card payments ON above and pay a test invoice with PayFast's sandbox test card. It should become paid and email a receipt.
- When you are happy, put your live details in the file and change
'sandbox'to'live'. Make one small real payment first.
<?php
define('PAYFAST_MODE', 'sandbox'); // 'sandbox' to test, 'live' for real money
define('PAYFAST_MERCHANT_ID', 'your merchant id');
define('PAYFAST_MERCHANT_KEY', 'your merchant key');
define('PAYFAST_PASSPHRASE', 'your passphrase'); // set the same one in your PayFast account
Recent card payments
| When | Invoice | Invoice amount | Card fee | Charged | Result | Note |
|---|---|---|---|---|---|---|
| Loading… | ||||||
Bulk email
News for customers who agreed to receive it. Every email has an unsubscribe link.
Write an email
Each email starts with "Hi" and the customer's first name, and ends with the company name and an unsubscribe link. You don't need to add those.
Sent emails
| Sent | Subject | Delivered | Failed | Clicked | Possibly opened | Status |
|---|---|---|---|---|---|---|
| Loading… | ||||||
Error Log
Errors that people saw on screen. Ask them to send the Reference (ERR-...) shown in the red box.
Loading...
Security Centre
One page that shows whether the site looks safe. It only looks: it never deletes, moves or repairs anything.
Loading...
System Self-Test
A one-click check of PHP settings, required extensions, file permissions and database reachability - useful after your host changes anything, or if something starts behaving oddly with no clear error.
Loading...
Page not available
There is no such page. Use the menu on the left.
Blog / News
Manage posts shown on the website
| Title | Slug | Author | Status | Published | Actions |
|---|
Build history
Deployment log and live DB schema status
Loading...
Site Manual
Admin guide to using the dashboard
Loading...
Team Bank Accounts
VN and ZA accounts assigned by sender surname initial
Loading...
Loading...
Loading...
Loading...
Global Bank Accounts
Multi-currency accounts shown to customers on invoices
Loading...
VN Local Courier Rates
Vietnam-side pickup fees shown to customers. Rates stored in VND.
Loading...
Package Presets
Populate the "Quick select" dropdown on the booking form.
Loading...