Sign in to access documentation

Docs
Home Training Classifieds Forum Signed in as
Quick Start
Get up and running with TrashGeek in under 10 minutes.

1. Sign up

Visit trashgeek.app and click Get Started. Fill in your company name, phone, email, address, and create your owner login. You'll be redirected to your dashboard immediately.

2. Log in to the dashboard

Go to trashgeek.app/map.html and sign in with your company slug, username, and password.

3. Add your first dumpster

Click Dumpsters in the sidebar, then Add Dumpster. Enter a label (e.g. "BIN-001") and size. Pricing is pulled automatically from your rate sheet on the Pricing tab. Your inventory is ready to rent.

4. Create a rental

Click Rentals > New Rental. Fill in the customer details, select a dumpster, set dates and pricing, then click Create Rental. The rental appears on your fleet map and dispatch board.

5. Embed the quote widget on your website

Go to Settings > Embed Codes and copy the script tag onto any page of your website. Customers can request quotes directly — you'll get email, SMS, and dashboard notifications instantly.

API base URL

All API endpoints are available at https://trashgeek.app/api. Include your token on every request:

Authorization: Bearer eyJ...

Website pages

FileDescription
website/index.htmlMarketing landing page - pricing, features, contact form, sign-up / waitlist
website/map.htmlOperator dashboard - fleet map, rentals, dispatch, chat, reports, settings
website/reports.htmlReporting dashboard - Chart.js, 10+ report sections
website/driver.htmlDriver mobile app - stops, GPS trips, QR scanner, proof-of-delivery photos
website/portal.htmlCustomer self-service portal - view rentals, request pickups, chat, invoices
website/docs.htmlDeveloper documentation (this page)
website/training.htmlTraining guide - step-by-step walkthroughs with screenshots
website/widget.jsEmbeddable forms - quote, managed cleanup, contact (drop-in script tag)
Plans & Feature Gating
TrashGeek uses plan-based feature gating. Some API endpoints require a Hauler or Fleet plan.
Pickup
$0
5 dumpsters · 1 user · 5% fee
Hauler
$19.99/mo
50 dumpsters · 2 users · 3% fee
Fleet
$99.99/mo
Unlimited · 10 users · 2% fee

Free on all plans

Rentals, dispatch, scheduling, quotes, customers, fleet map, customer portal, reviews, directory listing, Stripe Connect payments, driver app, multi-language (EN/ES/FR).

Hauler+ features

These endpoints return 403 with upgrade_url for Pickup users:

EndpointFeature
/api/invoicesCustomer invoice management
/api/campaignsEmail campaign builder
/api/workflowsAutomated SMS/email chains
/api/escalationsOverdue escalation rules
/api/seasonal-pricingSeasonal rate calendar
/api/bulkBatch operations & CSV import

Fleet-only features

White-label branding, custom domain, custom SMTP, QuickBooks, Xero, Invoice Ninja, HubSpot, FreshBooks, and IoT integrations.

Error response

// 403 Forbidden
{
  "error": "This feature requires a Hauler or Fleet plan.",
  "plan": "pickup",
  "upgrade_url": "/pricing"
}
Authentication
TrashGeek uses JWT Bearer tokens scoped to a company.

Login flow

POST /api/auth/login
Content-Type: application/json

{
  "company_slug": "acme-hauling",
  "username":     "admin",
  "password":     "changeme123"
}
// 200 OK
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user": {
    "id":       1,
    "username": "admin",
    "role":     "owner",
    "company_id": 1
  }
}

Using the token

GET /api/rentals
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Login returns an access token (15 min) and a refresh token (30 days). Use the refresh endpoint to get a new access token without re-authenticating.

Token refresh

POST /api/auth/refresh
Content-Type: application/json

{ "refresh_token": "eyJ..." }

// Response:
{ "token": "eyJ...", "refresh_token": "eyJ..." }
Legacy tokens (without a type field) are still accepted for backward compatibility.

Roles

RolePermissions
ownerFull access - company settings, SMTP config, pricing, user management, everything below
adminUser management, dumpster add/delete
dispatcherRead/write rentals, appointments, quotes
driverView assigned stops, start trips, mark deliveries/pickups, upload proof photos

Multi-tenancy

Every API request is automatically scoped to the company_id embedded in the JWT. It is impossible for one company to access another company's data through the API.

Companies API
Company registration, profile, and settings.
MethodPathAuthDescription
POST /api/companies/register Public Register a new company and owner account.
GET /api/companies/me Any Get own company details and settings.
PATCH /api/companies/me Owner Update company name, address, pricing, SMTP settings.
POST /api/companies/me/logo Owner Upload company logo (multipart file upload).
GET /api/companies/signup-status Public Check if new sign-ups are open.
POST /api/companies/waitlist Public Join the waitlist (when sign-ups are closed).

Register body

{
  "company_name":   "Acme Hauling",
  "company_phone":  "555-1234",
  "company_email":  "info@acmehauling.com",
  "company_address":"123 Main St",
  "company_city":   "Sioux Falls",
  "company_state":  "SD",
  "company_zip":    "57101",
  "owner_username": "admin",
  "owner_email":    "owner@acmehauling.com",
  "owner_password": "changeme123"
}
Users & Auth API
Login, current user, and company user management.
MethodPathAuthDescription
POST/api/auth/loginPublicLog in - requires company_slug, username, password
POST/api/auth/refreshPublicRefresh access token - body: { refresh_token }
GET/api/auth/meAnyCurrent user info
GET/api/auth/usersAdminList all users in the company
POST/api/auth/usersAdminCreate a new user -body: { username, password, email, role }
PATCH/api/auth/users/:idAdminUpdate a user's details or password
POST/api/auth/verify-email?token=XXXPublicVerify email address. Returns styled HTML confirmation page. Token expires after 24 hours.
POST/api/auth/resend-verificationPublicResend verification email. Body: { email, company_slug }. Rate limited.

Email verification

When a new user is created, a verification email is sent with a tokenized link. The token is valid for 24 hours. Clicking the link calls POST /api/auth/verify-email?token=XXX and renders a styled confirmation page.

POST /api/auth/resend-verification
Content-Type: application/json

{
  "email":        "jane@example.com",
  "company_slug": "acme-hauling"
}
Rate limiting: The resend endpoint is rate limited to prevent abuse. Wait at least 60 seconds between requests for the same email.
Rentals API
Core rental lifecycle -create, update, track status.
MethodPathDescription
GET/api/rentalsList rentals -filterable by status, search, date range. Paginated.
GET/api/rentals/statsDashboard stat counts (active, overdue, revenue, etc.). Optional ?days=30|60|90|180|365|quarter to filter by date range.
GET/api/rentals/mapAll delivered rentals for the fleet map (address, customer, dumpster)
GET/api/rentals/:idSingle rental detail
POST/api/rentalsCreate a rental
PATCH/api/rentals/:idUpdate rental fields or payment status
POST/api/rentals/:id/overageAdd overage charge — send { scale_weight } (tons) for auto-calculated tonnage overage, or { amount, note } for manual charge
POST/api/rentals/bulkBatch operations -body: { ids, action: "approve" | "cancel" | "mark_paid" }
POST/api/rentals/:id/paymentRecord a payment -body: { amount, method, note }
POST/api/rentals/:id/approveApprove a pending rental (sends confirmation email + SMS)
GET/api/rentals/:id/invoiceRender invoice HTML view
DELETE/api/rentals/:idDelete rental

Key rental fields

FieldTypeDescription
statusenumpending · confirmed · delivered · picked_up · completed · cancelled
payment_statusenumunpaid · deposit_paid · paid
base_pricedecimalBase rental rate
mileage_upchargedecimalExtra fee for distance beyond free miles
extra_feedecimalAddon fees (mattress, tires, etc.)
total_pricedecimalSum of all fees
scale_weightdecimalActual weight in tons from dump scale ticket
total_milesdecimalGPS-calculated trip distance (auto-tracked via driver app)
delivery_datedateScheduled drop-off date
pickup_datedateScheduled pickup date

Scale weight & tonnage overages

After a dumpster is weighed at the dump, record the scale ticket weight to auto-calculate tonnage overages based on dumpster size limits.

POST /api/rentals/:id/overage
Authorization: Bearer eyJ...
Content-Type: application/json

{
  "scale_weight": 4.2
}

The server compares scale_weight (in tons) against the included tonnage for the dumpster size. If the weight exceeds the limit, an overage charge is automatically calculated using the company's configured overage rate ($/ton) and added to the rental total.

// 200 OK
{
  "overage_tons":   1.2,
  "overage_amount": 90.00,
  "scale_weight":   4.2,
  "included_tons":  3.0,
  "rate_per_ton":   75.00,
  "total_price":    465.00
}
Tip: You can also pass { amount, note } instead of scale_weight to add a manual overage charge without weight calculation.
Dumpsters API
Fleet management -add, edit, dispatch, return, archive, and delete dumpsters.
MethodPathAuthDescription
GET/api/dumpstersAnyList all dumpsters with current status and rental info
GET/api/dumpsters/availableAnyList dumpsters not currently assigned to an active rental
GET/api/dumpsters/availability?company=<slug>PublicAvailable counts by size (used by embed widget)
GET/api/dumpsters/lookup?label=XAnyFind dumpster by label (QR scan flow)
POST/api/dumpstersAdminAdd a dumpster
PATCH/api/dumpsters/:idAnyUpdate label, size, notes, or status
POST/api/dumpsters/:id/dispatchAnyMark dumpster as delivered to a rental
POST/api/dumpsters/:id/returnAnyReturn a deployed or full dumpster — completes the rental
POST/api/dumpsters/:id/dump-and-returnAnyPick up full dumpster, dump it, return to customer — body: { scale_weight?, dump_fee? }. Weight accumulates across cycles.
POST/api/dumpsters/:id/archiveAdminArchive / retire a dumpster -frees plan slot, preserves history
DELETE/api/dumpsters/:idAdminPermanently delete a dumpster (cannot be deployed)
GET/api/dumpsters/maintenanceAnyList dumpsters needing maintenance (predictive)
POST/api/dumpsters/:id/serviceAnyRecord a service event - body: { notes }
Archived dumpsters are hidden by default in the dashboard but can be viewed via the status filter.
Predictive maintenance: The /maintenance endpoint flags dumpsters based on rental count and time since last service. Proactive alerts are sent automatically.

Trailer Rentals

Dumpsters support an equipment_type field that distinguishes between traditional roll-off containers and trailers. When set to trailer, additional fields become available for vehicle and insurance tracking.

FieldTypeDescription
equipment_typeenumroll_off (default) or trailer
trailer_sizestringTrailer dimensions or size label (e.g. "16ft", "20ft")
vehicle_regstringVehicle registration number
vehicle_vinstringVehicle identification number
reg_numberstringRegistration plate number
insurance_providerstringInsurance company name
insurance_policystringInsurance policy number
insurance_expirydateInsurance expiration date
weight_capacitydecimalMaximum weight capacity in tons

Set equipment_type when creating or updating a dumpster via POST /api/dumpsters or PATCH /api/dumpsters/:id. The GET /api/dumpsters response includes equipment_type and all trailer-specific fields.

POST /api/dumpsters
Authorization: Bearer eyJ...
Content-Type: application/json

{
  "label": "TRL-001",
  "size": "20",
  "equipment_type": "trailer",
  "trailer_size": "20ft",
  "vehicle_reg": "ABC-1234",
  "vehicle_vin": "1HGCM82633A004352",
  "reg_number": "REG-5678",
  "insurance_provider": "National Hauler Insurance",
  "insurance_policy": "POL-99001",
  "insurance_expiry": "2027-03-15",
  "weight_capacity": 8.5
}
Rentals: When a trailer is dispatched to a rental, the rental automatically inherits the equipment_type from the dumpster. You can filter rentals by equipment type in the dashboard.
Appointments API
Schedule deliveries, pickups, and service calls.
MethodPathDescription
GET/api/appointmentsList appointments -filterable by date, type, status
GET/api/appointments/todayToday's appointments sorted by time
POST/api/appointmentsCreate appointment -body: { rental_id, type, scheduled_date, scheduled_time?, dumpster_id?, driver_notes?, assigned_driver? }
PATCH/api/appointments/:idUpdate appointment -supports assigned_driver, status, actual_date
GET/api/appointments/routeOptimized route ordering for today's stops (driver app)
POST/api/appointments/:id/actionDriver actions -body: { action: "dropped_off" | "picked_up" | "loaded_full" | "mark_empty", lat?, lng?, scale_weight? }
POST/api/appointments/:id/proofUpload proof-of-delivery photo (multipart file upload)
DELETE/api/appointments/:idDelete appointment

Driver actions

Drivers execute actions on appointments from the mobile app. Each action updates the appointment status, dumpster status, and optionally records GPS coordinates.

POST /api/appointments/:id/action
Authorization: Bearer eyJ...
Content-Type: application/json

{
  "action": "dropped_off",
  "lat":    41.8781,
  "lng":    -87.6298
}
ActionEffect
dropped_offMarks dumpster as deployed at the delivery address
picked_upMarks dumpster as returned, completes the rental. Schedules review email.
loaded_fullMarks dumpster as full — ready for swap or pickup
mark_emptyResets dumpster to deployed status after emptying

Proof-of-delivery photo

Upload a photo as proof of delivery or pickup. Sent as multipart form data.

POST /api/appointments/:id/proof
Authorization: Bearer eyJ...
Content-Type: multipart/form-data

photo: (binary file)
Photos are stored on the server and the URL is saved to the proof_photo column on the appointment. Photos are visible in the dashboard appointment detail view.

Update appointment

Update an appointment's details. Commonly used to add driver notes or change status for missed/cancelled appointments.

PATCH /api/appointments/:id
Authorization: Bearer eyJ...
Content-Type: application/json

{
  "driver_notes": "Gate code 1234, park on left side",
  "status":       "missed"
}

Supported status values for manual update: missed, cancelled.

Also see GET /api/schedule?month=YYYY-MM for a month-view calendar of all rentals.

Quotes & Forms API
Public lead capture forms (dumpster quote, managed cleanup, contact) and internal quote management.
MethodPathAuthDescription
POST/api/quotes?company=<slug>PublicSubmit a form -quote, cleanup request, or contact message
GET/api/quotesAnyList quote requests -filterable by status
PATCH/api/quotes/:idAnyUpdate quote status: new · contacted · converted · no_response. Setting status to converted auto-creates a pending rental from the quote data.
DELETE/api/quotes/:idAnyDelete quote
POST/api/quotes/:id/follow-upAnySend follow-up to quoted customer. Auto-marks quote as contacted.

Form types -service_type

All three embeddable forms post to the same endpoint. The service_type field distinguishes them.

service_typeForm nameExtra fields
dumpster_quoteDumpster Quotesize, duration_type, delivery_date, address
managed_cleanupManaged Cleanupcleanup_type (junk_removal | estate_cleanout | demo | yard | other), property_size, preferred_date, details
contactContact Uscontact_subject (general | billing | service | other), message

POST body -dumpster quote

POST /api/quotes?company=acme-dumpsters
{
  "service_type":   "dumpster_quote",
  "customer_name":  "Jane Smith",
  "customer_email": "jane@example.com",
  "customer_phone": "555-1234",
  "size":           "20",
  "duration_type":  "week",
  "delivery_date":  "2025-07-10",
  "address":        "123 Main St, Springfield, IL",
  "promo_code":     "SAVE-AB12"
}

POST body -managed cleanup

POST /api/quotes?company=acme-dumpsters
{
  "service_type":   "managed_cleanup",
  "customer_name":  "Bob Jones",
  "customer_email": "bob@example.com",
  "customer_phone": "555-5678",
  "cleanup_type":   "estate_cleanout",
  "property_size":  "3_bedroom",
  "preferred_date": "2025-07-15",
  "details":        "3-bedroom house, lots of furniture"
}

POST body -contact us

POST /api/quotes?company=acme-dumpsters
{
  "service_type":      "contact",
  "customer_name":     "Alice Brown",
  "customer_email":    "alice@example.com",
  "customer_phone":    "555-9012",
  "contact_subject":   "billing",
  "message":           "I have a question about my last invoice."
}
On submission, an email alert is sent to the company's configured Quote Alert Email (set under Settings in the dashboard). The subject line and body clearly state the form type. If a promo_code is included, it is validated and the discount is applied to the estimated total.
When a quote is converted (status: "converted"), a pending rental is auto-created along with a delivery appointment. If a promo code was applied, it is automatically redeemed. The customer receives a booking confirmation email and SMS.

Quote follow-up

Send a follow-up message to a customer who submitted a quote. The quote status is automatically set to contacted.

POST /api/quotes/:id/follow-up
Authorization: Bearer eyJ...
Content-Type: application/json

{
  "channel": "both",
  "message": "Hi Jane, just following up on your dumpster quote. Ready to book?"
}
FieldTypeDescription
channelstringemail, sms, or both
messagestringCustom follow-up message body
Pricing API
Public rate sheet and server-side price estimation.
MethodPathAuthDescription
GET/api/pricing?company=<slug>PublicGet the company's published rate sheet (sizes, addon fees, included tonnage, overage rates, mileage)
GET/api/pricing/sizes?company=<slug>PublicGet distinct available dumpster sizes -used to populate embed widget dropdowns
POST/api/pricing/estimateAnyCalculate a full price estimate -body: { size, days, addons, address }

Pricing JSON structure

Update via PATCH /api/companies/me. Any omitted fields fall back to defaults.

{
  "pricing": {
    "rental_rates": {
      "10": { "daily": 175, "weekend": 220, "week": 260, "extended": null },
      "15": { "daily": 220, "weekend": 275, "week": 315, "extended": null },
      "20": { "daily": 285, "weekend": 315, "week": 375, "extended": null },
      "30": { "daily": 350, "weekend": 400, "week": 460, "extended": null },
      "40": { "daily": 425, "weekend": 480, "week": 550, "extended": null }
    },
    "addon_fees": {
      "mattress":   30,
      "box_spring": 30,
      "tire":       10,
      "lcd_tv":     20
    },
    "included_tons": {
      "10": 1, "15": 1.5, "20": 2, "30": 3, "40": 4
    },
    "weight_fees": {
      "10": 40, "15": 48, "20": 62, "30": 75, "40": 90
    },
    "mileage": {
      "rate_per_mile": 0.70,
      "free_miles":    20
    }
  }
}

Tonnage overage calculation

When a scale weight is recorded on a rental, the overage is auto-calculated: (scale_weight - included_tons[size]) × weight_fees[size]. Only the tonnage exceeding the included amount is charged. For example, a 20 yd dumpster weighing 3.5 tons: (3.5 - 2) × $62 = $93.00 overage.

Reports API
Business intelligence endpoints -all scoped to the authenticated company.
MethodPathDescription
GET/api/reports/revenueGross revenue, collected revenue, and rental count by period
GET/api/reports/rentalsRental volume by period, status, and dumpster size
GET/api/reports/utilizationPer-dumpster days deployed, utilization %, and total revenue
GET/api/reports/customersTop customers by revenue -?limit=10 (max 50)
GET/api/reports/overdueDelivered rentals past their scheduled pickup date
GET/api/reports/agingUnpaid invoices bucketed by 0-30 / 31-60 / 61-90 / 90+ days
GET/api/reports/quotesQuote volume and conversion rate by period
GET/api/reports/driversDriver performance metrics
GET/api/reports/heatmapGeographic heatmap data
GET/api/reports/marginsRental margin analysis
GET/api/reports/forecastDemand forecast
GET/api/reports/no-show-riskNo-show risk scoring
GET/api/reports/clv-cohortsCustomer lifetime value cohorts
GET/api/reports/export/:typeCSV export (type: revenue, rentals, customers, etc.)

Saved reports

MethodPathDescription
GET/api/reports/savedList saved report configurations
POST/api/reports/savedSave a report configuration
DELETE/api/reports/saved/:idDelete a saved report

Query parameters

ParamDefaultDescription
fromJan 1 of current yearStart date -YYYY-MM-DD
toTodayEnd date -YYYY-MM-DD
periodmonthmonth or day -grouping granularity

Example: revenue report

GET /api/reports/revenue?from=2024-01-01&to=2024-12-31&period=month

// Response:
{
  "data": [
    { "period": "2024-01", "rental_count": 12, "gross_revenue": "4800.00", "collected_revenue": "3600.00" },
    ...
  ],
  "totals": {
    "gross_revenue": "48000.00",
    "collected_revenue": "36000.00",
    "rental_count": 120,
    "avg_rental_value": "400.00"
  },
  "from": "2024-01-01",
  "to": "2024-12-31"
}
QuickBooks Integration
OAuth2 connection and invoice export to QuickBooks Online.
MethodPathAuthDescription
GET/api/integrations/quickbooks/connectAdminRedirect to QuickBooks OAuth2 consent screen
GET/api/integrations/quickbooks/callbackIntuitOAuth2 callback -stores access + refresh tokens
GET/api/integrations/quickbooks/statusAnyReturns { connected, realm_id, sandbox, token_expires }
POST/api/integrations/quickbooks/exportAdminExport rentals as QB invoices -body: { rental_ids: [1,2,3] }
DELETE/api/integrations/quickbooks/disconnectAdminRevoke token and clear QB credentials

Export response

POST /api/integrations/quickbooks/export
{ "rental_ids": [42, 43, 44] }

// Response:
{
  "results": [
    { "rental_id": 42, "qb_invoice_id": "156", "qb_doc_number": "1001", "status": "exported" },
    { "rental_id": 43, "qb_invoice_id": "157", "qb_doc_number": "1002", "status": "exported" },
    { "rental_id": 44, "status": "error", "error": "Customer not found" }
  ]
}
The export finds or creates a QB Customer by DisplayName (customer name), then creates an Invoice with three possible line items: base rental, mileage upcharge, and extra fees. Tokens are automatically refreshed when expired.
Stripe Connect
Collect customer payments directly via your own Stripe account.

Setup flow

  1. Company clicks Connect Stripe in the dashboard Settings page.
  2. Frontend calls GET /api/billing/connect/start -receives an onboarding URL.
  3. User completes Stripe Express onboarding.
  4. Stripe redirects back to /api/billing/connect/return -account is marked enabled.
  5. Company can now generate Payment Links on any rental.

Generate a Payment Link

POST /api/billing/connect/payment-link
Authorization: Bearer <token>
{ "rental_id": 42, "amount_cents": 35000, "description": "20yd Dumpster Rental" }

// Response:
{ "url": "https://buy.stripe.com/..." }

The link URL is stored on the rental record and displayed in the rental detail panel.

Messages & Real-time
Internal staff messaging and live dispatch updates over Socket.io.
MethodPathAuthDescription
GET/api/messages?with=<userId>AnyFetch message thread between current user and another user
POST/api/messagesAnySend a message -body: { to_user_id, body }

Socket.io rooms & events

Connect to wss://<host> with { auth: { token } }. The server automatically joins the socket to the company room (company:<id>) on connect.

EventDirectionPayload
joinClient → Server{ company_id } -join company room
messageServer → ClientNew message object broadcast to company room
rental_updatedServer → ClientRental record changed -dispatch board refreshes
appointment_updatedServer → ClientAppointment record changed -dispatch board refreshes
// Browser example
const socket = io('https://trashgeek.app', {
  auth: { token: localStorage.getItem('token') }
});

socket.on('message', msg => console.log('New message:', msg));
socket.on('rental_updated', rental => refreshDispatch(rental));
Embed Widget
Drop customer-facing forms onto any website with two lines of HTML.

Usage

Add a container with class trashgeek-widget and your company slug + form type, then include the script:

<!-- Dumpster Quote form -->
<div class="trashgeek-widget"
     data-company="acme-dumpsters"
     data-form="quote"></div>

<!-- Managed Cleanup request form -->
<div class="trashgeek-widget"
     data-company="acme-dumpsters"
     data-form="cleanup"></div>

<!-- Contact Us form -->
<div class="trashgeek-widget"
     data-company="acme-dumpsters"
     data-form="contact"></div>

<script src="https://trashgeek.app/widget.js"></script>

Form types

data-formFields collected
quoteName, email, phone, dumpster size (populated from live inventory), rental duration, delivery date, address
cleanupName, email, phone, cleanup type, property size, preferred date, details
contactName, email, phone (optional), subject, message
The quote form fetches available dumpster sizes in real time from /api/pricing/sizes?company=<slug> -customers can only select sizes that are currently in stock.

Copy embed snippets

Pre-filled snippets for all three form types are available in the dashboard under Settings → Embed Codes. Each snippet includes your company slug and a one-click copy button.

Pricing Configuration
How per-company pricing works and how to configure it.

Pricing is deep-merged over built-in defaults, so you only need to specify the values you want to override.

Default rates

SizeDailyWeekendWeek
10 yd$175$220$260
15 yd$220$275$315
20 yd$285$315$375
30 yd$350$400$460
40 yd$425$480$550

Default addon fees

ItemFee
Mattress$30
Box Spring$30
Tire$10
LCD TV$20

Default mileage

SettingDefault
Rate per mile$0.70
Free miles20

Update pricing

PATCH /api/companies/me
Authorization: Bearer <owner-token>

{
  "pricing": {
    "rental_rates": {
      "20": { "daily": 300, "weekend": 340, "week": 400, "extended": null }
    },
    "mileage": {
      "rate_per_mile": 0.85,
      "free_miles": 15
    }
  }
}
Only overrides: Only the keys you include will be changed. Other sizes and settings remain at their defaults.
Customers API
Manage your customer database with full CRUD and rental history.
MethodPathDescription
GET/api/customersList customers - searchable, paginated
POST/api/customersCreate a customer
GET/api/customers/:idCustomer detail with rental history
PATCH/api/customers/:idUpdate customer
DELETE/api/customers/:idDelete customer
POST/api/customers/importBulk CSV import -multipart file upload
Seasonal Pricing
Time-based pricing rules, package bundles, subscription contracts, fleet availability, and volume discounts.

Seasonal rules

MethodPathAuthDescription
GET/api/seasonal-pricingAnyList seasonal pricing rules
POST/api/seasonal-pricingAdminCreate a seasonal rule
PATCH/api/seasonal-pricing/:idAdminUpdate a seasonal rule
DELETE/api/seasonal-pricing/:idAdminDelete a seasonal rule

Package bundles

MethodPathAuthDescription
GET/api/seasonal-pricing/bundlesAnyList package bundles
POST/api/seasonal-pricing/bundlesAdminCreate bundle
PATCH/api/seasonal-pricing/bundles/:idAdminUpdate bundle
DELETE/api/seasonal-pricing/bundles/:idAdminDelete bundle

Subscription contracts

MethodPathAuthDescription
GET/api/seasonal-pricing/contractsAnyList subscription contracts
POST/api/seasonal-pricing/contractsAdminCreate contract
PATCH/api/seasonal-pricing/contracts/:idAdminUpdate contract
DELETE/api/seasonal-pricing/contracts/:idAdminCancel contract

Availability & discounts

MethodPathDescription
GET/api/seasonal-pricing/availabilityFleet availability % per dumpster size
GET/api/seasonal-pricing/volume-discountCheck volume discount for a customer
Bulk Operations
Batch actions on multiple rentals at once. Max 50 per batch.
MethodPathDescription
POST/api/bulk/approveApprove multiple rentals - body: { rental_ids: [1,2,3] }
POST/api/bulk/invoiceGenerate Stripe Payment Links for multiple rentals
POST/api/bulk/smsSend SMS to customers - body: { rental_ids, message }
POST/api/bulk/price-adjustAdjust prices - body: { rental_ids, adjustment_type, amount }

Price adjustment types

adjustment_typeExample
percentage{ "amount": 10 } adds 10% to each rental
fixed{ "amount": 25 } adds $25 to each rental
Customer Portal
Self-service portal for customers to view rentals, request pickups, and chat. Uses separate JWT type.
MethodPathAuthDescription
POST/api/portal/generateAnyGenerate a portal link for a customer
GET/api/portal/mePortalCustomer info
GET/api/portal/rentalsPortalCustomer's rentals
POST/api/portal/rentals/:id/request-pickupPortalRequest early pickup or reschedule
GET/api/portal/rentals/:id/photosPortalProof-of-delivery photos
GET/api/portal/rentals/:id/invoicePortalRender invoice HTML
GET/api/portal/availabilityPortalEquipment availability

Portal chat

MethodPathAuthDescription
GET/api/portal/chatPortalGet chat messages (customer side)
POST/api/portal/chatPortalSend chat message (customer side)
GET/api/portal/chat/:customerIdAnyRead chat thread (company side)
POST/api/portal/chat/:customerIdAnyReply to customer (company side)
Portal tokens use a separate JWT type: { type: "customer_portal", customer_id, company_id }. They do not grant access to any operator endpoints.

Portal Payments

Customers can pay invoices directly from their portal link via Stripe Checkout. Enable with portal_payments_enabled in company settings.

MethodPathAuthDescription
GET/api/portal/invoicesPortalList customer's invoices with status and amounts
POST/api/portal/invoices/:id/payPortalCreate Stripe Checkout session for invoice payment
Payments are processed via the company's connected Stripe account. Platform fees only apply to Stripe payments and are split automatically based on plan tier.
Reviews
Collect and display customer reviews. Review request emails are sent 1–2 hours after dumpster pickup (configurable). Includes $25-off coupon and customer referral bonus. Embed published testimonials on your website.
MethodPathAuthDescription
GET/api/reviews/submit?token=xxxPublicSelf-contained HTML review form
POST/api/reviews/submitPublicSave a review; returns promo code + referral link
GET/api/reviews/company/:slugPublicPublished reviews + average rating
GET/api/reviews/embed/:slugPublicEmbeddable testimonials widget (iframe)
GET/api/reviewsAnyList reviews for your company
POST/api/reviews/request/:rentalIdAnySend a review request to the customer
PATCH/api/reviews/:idAdminUpdate review status (approve, hide)
GET/api/reviews/promo-codesAnyList promo codes for your company
GET/api/reviews/promo-codes/lookup?code=XXXPublicValidate a promo code
PATCH/api/reviews/promo-codes/:id/redeemAnyMark a promo code as redeemed
Locations
Multi-location support - link dumpsters and rentals to specific yards or depots.
MethodPathAuthDescription
GET/api/locationsAnyList locations
POST/api/locationsAdminCreate a location
PATCH/api/locations/:idAdminUpdate a location
DELETE/api/locations/:idAdminDelete a location
Referrals
Refer other companies and both get 1 free month of service. Referrals accrue — refer 5, get 5 months free. Codes follow the format TG-XXXXXXXX. The /code endpoint also returns free_months — the company's accrued referral credit balance.
MethodPathDescription
GET/api/referrals/codeGet or create your referral code
GET/api/referralsList your referrals and their status
POST/api/referrals/inviteSend a referral invite email
Damage Reports API
Track dumpster damage, upload photos, and manage insurance claims.
MethodPathAuthDescription
GET/api/damageAnyList damage reports for company. Filter by status and severity query params.
POST/api/damageAnyCreate a damage report
PATCH/api/damage/:idAnyUpdate damage report status, insurance info
POST/api/damage/:id/photoAnyUpload damage photo (multipart form data). Optional type field: pre or post.

Create a damage report

POST /api/damage
Authorization: Bearer eyJ...
Content-Type: application/json

{
  "rental_id":   42,
  "dumpster_id": 7,
  "description": "Cracked side panel from forklift impact",
  "severity":    "moderate",
  "repair_cost": 350.00
}

Severity levels

SeverityDescription
minorCosmetic damage — dumpster still usable
moderateStructural concern — may need repair before next rental
majorSignificant damage — dumpster out of service until repaired

Upload damage photo

Attach photos to a damage report. Use the optional type field to distinguish between pre-repair and post-repair photos.

POST /api/damage/:id/photo
Authorization: Bearer eyJ...
Content-Type: multipart/form-data

photo: (binary file)
type: pre
Insurance tracking: Use PATCH /api/damage/:id to attach insurance claim numbers, adjuster notes, and resolution status to damage reports.
Escalations
Automated escalation rules for overdue, unpaid, and unresponsive rentals.
MethodPathAuthDescription
GET/api/escalationsAnyList escalation rules
POST/api/escalationsAdminCreate an escalation rule
PATCH/api/escalations/:idAdminUpdate a rule
DELETE/api/escalations/:idAdminDelete a rule
Escalation rules are evaluated automatically. Available conditions: overdue_days, unpaid_days, no_response_days. Actions: send_sms, send_email, notify_matrix.
Workflows
Event-driven automation with configurable steps. Trigger workflows on rental or appointment events.
MethodPathDescription
GET/api/workflowsList workflows
GET/api/workflows/:idSingle workflow with steps
POST/api/workflowsCreate workflow with steps
PATCH/api/workflows/:idUpdate name, trigger_event, active flag
DELETE/api/workflows/:idDelete workflow
PUT/api/workflows/:id/stepsReplace all steps for a workflow
Trips
Driver GPS trip tracking - start, complete, and review trip legs.
MethodPathDescription
POST/api/tripsStart a trip leg - body: { appointment_id, start_lat, start_lng }
PATCH/api/trips/:idComplete a trip leg - body: { end_lat, end_lng }
GET/api/tripsList trips
Schedule
Monthly calendar view and iCal feed for dispatch scheduling.
MethodPathAuthDescription
GET/api/schedule?month=YYYY-MMAnyMonthly schedule view of all rentals
GET/api/schedule/ical?token=<calendar_token>PubliciCal feed - subscribe in any calendar app
Directory
Public consumer search - find nearby dumpster rental companies by location.
MethodPathAuthDescription
GET/api/directory/search?lat=X&lng=Y&radius=50PublicFind nearby companies
GET/api/directory/company/:slugPublicPublic company profile
Xero Integration
OAuth2 connection and invoice export to Xero.
MethodPathAuthDescription
GET/api/integrations/xero/connectAdminStart OAuth2 flow
GET/api/integrations/xero/callbackXeroOAuth2 callback
GET/api/integrations/xero/statusAdminConnection status
POST/api/integrations/xero/exportAdminExport rentals as Xero invoices - body: { rental_ids }
DELETE/api/integrations/xeroAdminDisconnect Xero

Environment variables

VariableDescription
XERO_CLIENT_IDXero OAuth2 client ID
XERO_CLIENT_SECRETXero OAuth2 client secret
XERO_REDIRECT_URIOAuth2 callback URL
HubSpot CRM
Sync customers as contacts and rentals as deals in HubSpot.
MethodPathAuthDescription
GET/api/integrations/hubspot/connectAdminStart OAuth2 flow
GET/api/integrations/hubspot/callbackHubSpotOAuth2 callback
GET/api/integrations/hubspot/statusAdminConnection status
POST/api/integrations/hubspot/sync-contactsAdminPush customers as HubSpot contacts
POST/api/integrations/hubspot/sync-dealsAdminPush rentals as HubSpot deals
GET/api/integrations/hubspot/contactsAdminList synced contacts
DELETE/api/integrations/hubspot/disconnectAdminClear tokens and disconnect

Environment variables

VariableDescription
HUBSPOT_CLIENT_IDHubSpot OAuth2 client ID
HUBSPOT_CLIENT_SECRETHubSpot OAuth2 client secret
HUBSPOT_REDIRECT_URIOAuth2 callback URL
FreshBooks
Export rental invoices to FreshBooks via OAuth2.
MethodPathAuthDescription
GET/api/integrations/freshbooks/connectAdminStart OAuth2 flow
GET/api/integrations/freshbooks/callbackFreshBooksOAuth2 callback
GET/api/integrations/freshbooks/statusAdminConnection status
POST/api/integrations/freshbooks/exportAdminExport rentals as FreshBooks invoices
DELETE/api/integrations/freshbooks/disconnectAdminClear tokens and disconnect

Environment variables

VariableDescription
FRESHBOOKS_CLIENT_IDFreshBooks OAuth2 client ID
FRESHBOOKS_CLIENT_SECRETFreshBooks OAuth2 client secret
FRESHBOOKS_REDIRECT_URIOAuth2 callback URL
Invoice Ninja
Self-hosted open-source invoicing. Connect via API key and export rental invoices to your Invoice Ninja instance.
MethodPathAuthDescription
POST/api/integrations/invoiceninja/connectAdminSave Invoice Ninja API key and base URL
GET/api/integrations/invoiceninja/statusAdminConnection status
POST/api/integrations/invoiceninja/exportAdminExport rentals as Invoice Ninja invoices
DELETE/api/integrations/invoiceninja/disconnectAdminClear API key and disconnect

Environment variables

VariableDescription
INVOICENINJA_URLBase URL of your Invoice Ninja instance (e.g. https://invoicing.example.com)
INVOICENINJA_API_KEYInvoice Ninja API token
Self-hosted: Invoice Ninja runs on your own server, so your financial data never leaves your infrastructure. TrashGeek connects via the Invoice Ninja v5 REST API.
IoT Tracking
Real-time GPS, weight, temperature, and alert data from IoT-enabled dumpsters via HMAC-authenticated webhooks.
MethodPathAuthDescription
POST/api/integrations/iot/webhookHMACReceive IoT events (GPS, weight, temp, alert)
GET/api/integrations/iot/eventsAnyList recent IoT events
GET/api/integrations/iot/events/:dumpsterIdAnyEvents for a specific dumpster
POST/api/integrations/iot/configureAdminSet webhook HMAC secret
GET/api/integrations/iot/statusAnyConfiguration status
HMAC verification: The IoT webhook validates the X-Signature header using HMAC-SHA256 with your configured secret.
Google Business Profile
Manage your Google Business listing - post reviews, update hours, and select locations.
MethodPathAuthDescription
GET/api/integrations/gbp/connectAdminStart OAuth2 flow
GET/api/integrations/gbp/callbackGoogleOAuth2 callback
GET/api/integrations/gbp/statusAnyConnection status
GET/api/integrations/gbp/locationsAdminList business locations
POST/api/integrations/gbp/select-locationAdminSave selected location
POST/api/integrations/gbp/post-reviewAdminPost a review as a local post
POST/api/integrations/gbp/update-hoursAdminUpdate business hours
DELETE/api/integrations/gbp/disconnectAdminClear tokens and disconnect

Environment variables

VariableDescription
GBP_CLIENT_IDGoogle OAuth2 client ID
GBP_CLIENT_SECRETGoogle OAuth2 client secret
GBP_REDIRECT_URIOAuth2 callback URL
Webhooks
Register custom webhooks to receive real-time event notifications at your own endpoints.
MethodPathDescription
GET/api/webhooksList your webhooks
POST/api/webhooksCreate a webhook - body: { url, events }
PATCH/api/webhooks/:idUpdate webhook URL or events
DELETE/api/webhooks/:idDelete webhook
POST/api/webhooks/:id/testSend a test ping
Webhook payloads are signed with a per-webhook secret (returned on creation). Verify the X-Webhook-Signature header using HMAC-SHA256.
Push Notifications
Web Push (VAPID) for real-time browser notifications. Requires the push_notifications feature flag.
MethodPathAuthDescription
GET/api/push/vapid-keyPublicReturn VAPID public key
POST/api/push/subscribeAnySave push subscription
DELETE/api/push/unsubscribeAnyRemove push subscription

Environment variables

VariableDescription
VAPID_PUBLIC_KEYVAPID public key for Web Push
VAPID_PRIVATE_KEYVAPID private key for Web Push
VAPID_EMAILContact email for VAPID (e.g. mailto:admin@example.com)
WebAuthn (Passkeys)
Passwordless login via biometrics and security keys. Requires the webauthn feature flag.
MethodPathAuthDescription
POST/api/webauthn/register/optionsAnyGenerate registration challenge
POST/api/webauthn/register/verifyAnyStore credential after registration
POST/api/webauthn/login/optionsPublicGenerate login challenge
POST/api/webauthn/login/verifyPublicVerify assertion and return JWT
SMS Inbound
Receive inbound SMS messages from customers via Twilio webhook.
MethodPathAuthDescription
POST/api/sms/inboundTwilioTwilio inbound webhook
Configure your Twilio phone number's webhook URL to https://yourapi.com/api/sms/inbound. Incoming messages are matched to customers and displayed in the dashboard.
Classifieds & Community Forum
Equipment marketplace, community forum with knowledge base, spam defence, featured listings, and reply notifications. All endpoints are prefixed with /api/classifieds.

Forum Endpoints

MethodPathAuthDescription
GET/api/classifieds/forum/categoriesPublicList forum categories
GET/api/classifieds/forum/threadsPublicList threads (filter by category, search)
GET/api/classifieds/forum/pinnedPublicKnowledge base — all pinned threads
POST/api/classifieds/forum/threadsUserCreate thread (rate limited: 1/60s). Auto-flags links from low-post users.
POST/api/classifieds/forum/threads/:id/replyUserReply to thread (rate limited: 1/30s). Sends email notification to author.

Listings Endpoints

MethodPathAuthDescription
GET/api/classifieds/listingsPublicBrowse listings. Featured listings sort first. Returns is_featured flag.
POST/api/classifieds/listingsUserCreate listing (rate limited: 1/120s). Auto-flags new accounts with URLs.
PATCH/api/classifieds/admin/listings/:id/featureAdminFeature/unfeature a listing. Body: { featured: 1, days: 7 }

Spam Defence

  • Honeypot: Hidden website field on registration — bots that fill it get a fake 201 response
  • Rate limiting: Per-user cooldowns on thread posts (60s), replies (30s), and listings (120s)
  • Auto-flagging: Posts with URLs from accounts <24h old or users with <5 posts are auto-flagged for review

Admin Moderation

MethodPathAuthDescription
GET/api/classifieds/admin/forum-flagsAdminList unresolved forum content flags
PATCH/api/classifieds/admin/forum-flags/:id/resolveAdminResolve a forum flag

Reply Notifications

When someone replies to a thread, the thread author receives an email notification (if notify_replies = 1). Users can toggle this in their profile or click the unsubscribe link in the email. The GET /api/classifieds/unsubscribe?token=xxx endpoint handles one-click unsubscribe.
Smart Dispatch & Route Optimization
Kanban-style dispatch board, live driver GPS on the fleet map, auto-swap scheduling, and time window support for appointments.

Dispatch Board

The dispatch board provides a Kanban drag-and-drop interface for managing daily appointments. Columns represent statuses (Pending, Dispatched, In Progress, Completed) and drivers can be reassigned by dragging cards between lanes.

MethodPathAuthDescription
GET/api/dispatch/boardAnyGet dispatch board state grouped by status
PATCH/api/dispatch/:id/assignAnyAssign or reassign a driver - body: { driver_id }
PATCH/api/dispatch/:id/statusAnyMove card to a new column - body: { status }
PATCH/api/dispatch/:id/reorderAnyReorder card within a column - body: { position }

Live Driver GPS Tracking

Active drivers broadcast their GPS position in real time. The fleet map shows live driver markers that update continuously, giving dispatchers full visibility into driver locations.

MethodPathAuthDescription
POST/api/dispatch/gpsDriverReport driver GPS position - body: { lat, lng }
GET/api/dispatch/drivers/liveAnyGet all active driver positions for the fleet map

Auto-Swap Scheduling

When a dumpster is marked full, the system automatically schedules a swap appointment — picking up the full container and delivering a replacement. No manual intervention required.

MethodPathAuthDescription
POST/api/dispatch/auto-swapAnyTrigger auto-swap for a full dumpster - body: { dumpster_id }
GET/api/dispatch/auto-swap/settingsOwnerGet auto-swap configuration
PATCH/api/dispatch/auto-swap/settingsOwnerUpdate auto-swap settings

Auto-Pickup Scheduling

When a rental's preferred pickup date is tomorrow, the system automatically marks the dumpster as full and creates a pickup appointment for the pickup date. This runs daily at 7 AM. If a pickup appointment already exists for the rental (e.g. manually created by the dispatcher), a duplicate is not created.

Auto-scheduled pickups appear on the dispatch board as scheduled status. Dispatchers can reassign drivers, change the date, or cancel the appointment as needed. A Matrix/chat notification is sent when pickups are auto-scheduled.

Time Windows

Appointments support time window preferences: morning (before noon), afternoon (noon–5 PM), or any (all day). Time windows are shown on the dispatch board and used for route ordering.

Set the time_window field when creating or updating appointments. Valid values: morning, afternoon, any.
Customer Payments & Invoicing
Create and send invoices, accept online payments via Stripe checkout, set up recurring contract billing, and let customers pay from the portal.

Invoice Management

MethodPathAuthDescription
GET/api/invoicesAnyList invoices (filterable by status, customer, date range)
POST/api/invoicesAnyCreate an invoice - body: { customer_id, items[], due_date }
GET/api/invoices/:idAnyGet invoice detail with line items
PATCH/api/invoices/:idAnyUpdate invoice (draft only)
POST/api/invoices/:id/sendAnySend invoice to customer via email
PATCH/api/invoices/:id/voidOwnerVoid an invoice

Stripe Checkout

Invoices include a Pay Now button that creates a Stripe Checkout session. Customers complete payment on the Stripe-hosted page and are redirected back to the portal.

MethodPathAuthDescription
POST/api/invoices/:id/checkoutAnyCreate Stripe Checkout session for invoice payment
POST/api/invoices/stripe-webhookStripeWebhook handler - marks invoice paid on successful charge

Recurring Contract Billing

Customers with active contracts can be set to recurring billing. Configure a billing day (1–28) and the system auto-generates invoices each cycle.

MethodPathAuthDescription
GET/api/invoices/recurringAnyList recurring billing configurations
POST/api/invoices/recurringAnyCreate recurring config - body: { customer_id, billing_day, items[] }
PATCH/api/invoices/recurring/:idAnyUpdate or pause recurring billing
DELETE/api/invoices/recurring/:idOwnerCancel recurring billing

Customer Portal Invoice Tab

The customer portal includes an Invoices tab where customers can view all invoices and their statuses. Each unpaid invoice displays a Pay Now button that initiates Stripe Checkout directly from the portal — no login required.
Email Campaigns
Bulk email campaigns with targeting filters, draft/preview/send workflow, and unsubscribe handling.

Campaign Management

MethodPathAuthDescription
GET/api/campaignsAnyList all campaigns with stats (sent, opened, clicked)
POST/api/campaignsAnyCreate a campaign draft - body: { subject, body_html, filters }
GET/api/campaigns/:idAnyGet campaign detail with recipient list and stats
PATCH/api/campaigns/:idAnyUpdate campaign draft (subject, body, filters)
POST/api/campaigns/:id/previewAnySend a preview email to the logged-in user
POST/api/campaigns/:id/sendOwnerSend the campaign to all matched recipients
DELETE/api/campaigns/:idOwnerDelete a draft campaign

Targeting Filters

Campaigns can target customers based on filters such as:

  • Status: active, inactive, or all customers
  • Last rental date: before or after a given date
  • Location: customers at a specific location
  • Tags: customer tags for segmentation

Unsubscribe Handling

Every campaign email includes a one-click unsubscribe link. Unsubscribed customers are automatically excluded from future campaigns. The GET /api/campaigns/unsubscribe?token=xxx endpoint processes unsubscribe requests and displays a confirmation page.
Churn Detection & Winback
Automatic at-risk customer detection based on inactivity, winback email campaigns, and configurable alert thresholds.

At-Risk Detection

The system monitors customer activity and flags accounts as at-risk when they exceed the configured inactivity threshold (default: 90 days since last rental). At-risk customers appear in a dedicated dashboard section with recommended actions.

MethodPathAuthDescription
GET/api/churn/at-riskAnyList at-risk customers with last activity date and risk score
GET/api/churn/statsAnyChurn overview - total at-risk, winback success rate, trends

Winback Campaigns

Trigger automated winback emails to re-engage inactive customers. Winback emails can include personalized offers and discount codes to incentivize return bookings.

MethodPathAuthDescription
POST/api/churn/winbackAnySend winback email to customer - body: { customer_id, promo_code? }
POST/api/churn/winback/bulkOwnerSend winback to all at-risk customers

Configuration

MethodPathAuthDescription
GET/api/churn/settingsOwnerGet churn detection settings
PATCH/api/churn/settingsOwnerUpdate settings - body: { threshold_days, auto_winback_enabled }
When auto_winback_enabled is turned on, the system automatically sends a winback email when a customer first crosses the inactivity threshold. Each customer receives at most one automatic winback per 90-day window.
Driver GPS & ETA
Continuous GPS tracking during trips, real-time ETA notifications to customers via SMS, and GPS status indicators.

GPS Tracking

Drivers broadcast their GPS position continuously while on active trips. The driver app automatically manages tracking start/stop lifecycle tied to trip status.

MethodPathAuthDescription
POST/api/driver-gps/positionDriverReport GPS position - body: { lat, lng, accuracy, speed, heading }
GET/api/driver-gps/activeAnyGet all active driver positions with last update timestamps
GET/api/driver-gps/:driver_id/trailAnyGet GPS trail (breadcrumb path) for a driver's current trip

ETA Notifications

When a driver is en route, the system calculates the estimated time of arrival and sends an SMS notification to the customer with a live ETA. Customers receive updates when the driver departs and when the ETA changes significantly.

MethodPathAuthDescription
GET/api/driver-gps/:driver_id/eta/:appointment_idAnyCalculate current ETA to appointment destination
POST/api/driver-gps/notify-etaAnySend ETA SMS to customer - body: { appointment_id }

GPS Status Indicator

The fleet map and dispatch board display a GPS status indicator for each driver:

  • Green: GPS active, position updated within the last 60 seconds
  • Yellow: GPS stale, last update 1–5 minutes ago
  • Red: GPS offline, no update for over 5 minutes
GPS tracking requires the driver to grant location permissions in the browser. The driver app displays a prompt on trip start if permissions have not yet been granted.
Overflow Network
Route excess demand to nearby partner operators and earn referral fees on every accepted job. All endpoints are prefixed with /api/overflow.

How It Works

When your fleet is at capacity, incoming quotes can be automatically forwarded to partner operators within your configured service radius. When a partner accepts and completes the job, you earn a referral fee based on the percentage you set. Partners see overflow quotes in their dashboard and can accept or decline with one click.

Settings

MethodPathAuthDescription
GET/api/overflow/settingsOwnerGet overflow network settings (enabled, radius, referral %)
PATCH/api/overflow/settingsOwnerUpdate settings - body: { enabled, radius_miles, referral_pct }

Overflow Quotes

MethodPathAuthDescription
GET/api/overflow/quotesAnyList inbound overflow quotes available to your company
POST/api/overflow/quotes/:id/acceptAnyAccept an overflow quote and create a rental
POST/api/overflow/quotes/:id/declineAnyDecline an overflow quote

Referral Tracking

MethodPathAuthDescription
GET/api/overflow/referralsOwnerList referral fees earned and owed, with status and payout history
Overflow is available on all paid plans. The referring company sets the referral percentage (default 10%). Fees are tracked per completed job and appear in the referrals ledger for both parties.
Job Board
Post driver and CDL job openings, manage applications, and let job seekers browse listings publicly. All endpoints are prefixed with /api/jobs.

Job Postings

MethodPathAuthDescription
GET/api/jobsPublicBrowse active job listings (filter by location, type, CDL requirement)
GET/api/jobs/:idPublicGet a single job posting detail
POST/api/jobsOwnerCreate a job posting - body: { title, description, location, type, cdl_required, pay_range }
PATCH/api/jobs/:idOwnerUpdate a job posting
DELETE/api/jobs/:idOwnerClose / delete a job posting

Applications

MethodPathAuthDescription
POST/api/jobs/:id/applyPublicSubmit an application - body: { name, email, phone, message, resume_url }
GET/api/jobs/:id/applicationsOwnerList applications for a job posting
PATCH/api/jobs/applications/:idOwnerUpdate application status - body: { status } (new, reviewed, contacted, hired, rejected)

Application Flow

Job seekers browse the public /jobs page, filter by location and type, and submit applications with their contact details and optional resume link. The posting company receives an email notification for each new application. Applications can be reviewed and advanced through statuses directly from the dashboard.

Job postings are available on all plans. Listings are shown on the public jobs page and include your company name, location, and logo. Closed or expired postings are automatically hidden from public search.
Native Driver App
A dedicated mobile app for drivers built with Capacitor. Available on Android now, iOS coming soon.

Features

  • Background GPS tracking — continuous location reporting during active trips, even when the app is minimized
  • Native camera — proof-of-delivery and damage report photos with better quality than browser capture
  • QR code scanning — scan dumpster QR codes to dispatch, mark full, or return bins
  • Push notifications — native push alerts for new stops, schedule changes, and dispatch updates
  • Offline support — queue actions when offline, auto-sync when connectivity returns
  • Haptic feedback — vibration on successful scans and completed actions

Installation

The Android app is distributed as an APK. Contact your administrator for the install link. The app connects to the same backend as the web version — log in with your existing driver credentials.

The native app wraps the same driver interface you already use in the browser, enhanced with native device capabilities. All your stops, routes, and trip history stay in sync.
Auto-Ban & Intrusion Detection
Automatic threat detection and IP banning to protect the platform from malicious traffic.

How it works

The platform tracks suspicious requests per IP address in real time. Each failed authentication attempt, malformed request, or access to non-existent routes increments a suspicion counter. When the counter exceeds the configured threshold, the IP is automatically banned and all further requests are rejected with 403 Forbidden.

Configuration

Environment VariableDefaultDescription
INTRUSION_THRESHOLD50Number of suspicious requests before an IP is auto-banned
BAN_DURATION_MINUTES30How long an auto-ban lasts before the IP is allowed again

Bot honeypot

Common attack paths (e.g. /wp-admin, /.env, /phpmyadmin) are trapped by a honeypot layer. Requests to these paths receive a 404 response after a 3-second tarpit delay, and each hit counts as 10x suspicious — meaning bots trigger the auto-ban threshold much faster than regular users.

Matrix alerts: When an IP is auto-banned, a notification is sent to the configured Matrix room so administrators are immediately aware of the event.

Superadmin endpoints

MethodPathDescription
GET/api/superadmin/banned-ipsList all currently banned IPs and IPs with elevated suspicion scores
POST/api/superadmin/banned-ipsManually ban an IP
DELETE/api/superadmin/banned-ips/:ipUnban a specific IP address
DELETE/api/superadmin/banned-ipsClear all bans and reset suspicion counters
POST /api/superadmin/banned-ips
Authorization: Bearer eyJ...
Content-Type: application/json

{
  "ip": "203.0.113.42",
  "duration_minutes": 60,
  "reason": "Repeated brute-force attempts"
}
DELETE /api/superadmin/banned-ips/203.0.113.42
Authorization: Bearer eyJ...
Live Analytics
Real-time platform metrics and historical analytics for superadmins.

Real-time counters

MethodPathAuthDescription
GET/api/superadmin/liveSuperReal-time platform counters

Returns a snapshot of live platform activity:

GET /api/superadmin/live
Authorization: Bearer eyJ...

// 200 OK
{
  "requests_per_minute": 142,
  "active_sockets": 38,
  "unique_ips": 97,
  "status_codes": { "200": 1284, "304": 412, "401": 7, "404": 3 },
  "top_endpoints": [
    { "path": "/api/rentals", "count": 204 },
    { "path": "/api/dumpsters", "count": 187 }
  ],
  "recent_logins": [
    { "user": "jdcadmin", "company": "justins-dumpster-company", "at": "2026-03-10T14:32:00Z" }
  ],
  "activity_feed": [
    { "type": "rental_created", "company": "acme-hauling", "at": "2026-03-10T14:31:45Z" }
  ]
}

Platform analytics

MethodPathAuthDescription
GET/api/superadmin/analytics?range=7d|30d|24hSuperHistorical platform analytics

Returns aggregated platform metrics for the specified time range:

GET /api/superadmin/analytics?range=30d
Authorization: Bearer eyJ...

// 200 OK
{
  "daily_rentals": [ { "date": "2026-03-01", "count": 14 }, ... ],
  "daily_quotes": [ { "date": "2026-03-01", "count": 31 }, ... ],
  "daily_signups": [ { "date": "2026-03-01", "count": 2 }, ... ],
  "most_active_companies": [
    { "slug": "acme-hauling", "rentals": 87, "revenue": 12450.00 }
  ],
  "conversion_stats": {
    "quotes_to_rentals": 0.42,
    "trials_to_paid": 0.31
  },
  "forum_posts": 156,
  "listings_count": 42,
  "jobs_count": 18,
  "recent_users": [
    { "username": "newdriver", "company": "acme-hauling", "created_at": "2026-03-09T10:15:00Z" }
  ]
}
Both endpoints require superadmin authentication. The range parameter on /analytics accepts 24h, 7d, or 30d.