NextRouteNextRoute

Customers API

API reference for creating, listing, updating, and deleting customers and their properties.

Customers API

The Customers API lets you manage your customer records programmatically. All endpoints require a valid JWT token in the Authorization header.

List Customers

Retrieve a paginated list of customers with optional filters.

curl "https://api.nextroute.app/api/customers?page=1&limit=50&search=john" \
  -H "Authorization: Bearer YOUR_TOKEN"

Query Parameters:

ParameterTypeDefaultDescription
pageinteger1Page number
limitinteger50Results per page (max 200)
searchstringSearch by name, email, or address
zone_idstringFilter by service zone
plan_idstringFilter by service plan
statusstringFilter by billing status (active, pending, paused, canceled)
sortstringname_ascSort order: name_asc, name_desc, enrolled_newest, enrolled_oldest

Response (200):

{
  "data": [
    {
      "id": "cus_abc123",
      "name": "John Doe",
      "first_name": "John",
      "last_name": "Doe",
      "email": "john@example.com",
      "phone": "555-0100",
      "address": "123 Main St, Austin, TX 78701",
      "lat": 30.2672,
      "lng": -97.7431,
      "billing_status": "active",
      "service_plan_name": "Weekly Premium",
      "service_zone_name": "Central Austin",
      "property_count": 1
    }
  ],
  "total": 245,
  "page": 1,
  "limit": 50
}

Create Customer

Create a new customer record. If an address is provided, a property is automatically created and geocoded.

curl -X POST https://api.nextroute.app/api/customers \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "Jane",
    "last_name": "Smith",
    "email": "jane@example.com",
    "phone": "555-0200",
    "address": "456 Oak Ave, Austin, TX 78702",
    "service_plan_id": "sp_abc123",
    "service_zone_id": "sz_xyz789",
    "notes": "Gate code: 1234",
    "custom_fields_json": {
      "bin_count": 2,
      "bin_size": "96gal",
      "bin_location": "Side of house"
    }
  }'

Request Body:

FieldTypeRequiredDescription
namestringYes*Full name (*or provide first_name + last_name)
first_namestringYes*First name
last_namestringYes*Last name
emailstringNoEmail address
phonestringNoPhone number
addressstringNoService address (triggers property creation + geocoding)
service_plan_idstringNoAssign a service plan
service_zone_idstringNoAssign a service zone
notesstringNoInternal notes
custom_fields_jsonobjectNoVertical-specific custom fields
trash_daystringNoDay of week for trash pickup
trash_pickup_timestringNoMorning or afternoon

When a customer is created with an address:

  1. The address is geocoded via Mapbox
  2. A property record is created
  3. A Stripe customer is created (if email provided and Stripe is connected)
  4. Lifecycle hooks fire: welcome email, route template sync, etc.

Response (201): Returns the full customer object.

Update Customer

Update an existing customer's fields.

curl -X PUT https://api.nextroute.app/api/customers/cus_abc123 \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "555-0300",
    "billing_status": "active",
    "notes": "Updated gate code: 5678"
  }'

Updatable Fields: name, first_name, last_name, email, phone, address, lat, lng, service_plan_id, service_zone_id, billing_status, notes, custom_fields_json, enrolled_at

If address is updated without new lat/lng values, the address is automatically re-geocoded. Updating first_name or last_name automatically recomputes the composite name field.

Response (200): Returns the updated customer object.

Customer History

Retrieve a customer with their recent service history, invoices, and route template assignments.

curl https://api.nextroute.app/api/customers/cus_abc123/history \
  -H "Authorization: Bearer YOUR_TOKEN"

Response (200):

{
  "customer": { "id": "cus_abc123", "name": "John Doe", "service_plan_name": "Weekly Premium" },
  "recent_stops": [
    { "id": "stp_1", "route_date": "2026-03-22", "status": "completed", "completed_at": "2026-03-22T10:30:00Z" }
  ],
  "recent_invoices": [
    { "id": "inv_1", "total_cents": 7500, "status": "paid", "paid_at": "2026-03-01T12:00:00Z" }
  ],
  "template_stops": [
    { "template_name": "Monday - North Zone", "day_of_week": "monday", "zone_name": "North Zone" }
  ]
}

Bulk Import

Import multiple customers from a JSON array. Supports plan and zone matching by name.

curl -X POST https://api.nextroute.app/api/customers/import \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "customers": [
      { "name": "Alice Brown", "email": "alice@example.com", "address": "789 Pine St, Austin, TX", "service_plan_name": "Weekly Premium" },
      { "name": "Bob Wilson", "email": "bob@example.com", "address": "321 Elm St, Austin, TX", "service_zone_name": "South Austin" }
    ]
  }'

Response (200):

{
  "imported": 2,
  "errors": []
}

Delete Customer (Soft Delete)

Soft-delete a customer. The record is retained but excluded from active queries.

curl -X DELETE https://api.nextroute.app/api/customers/cus_abc123 \
  -H "Authorization: Bearer YOUR_TOKEN"

Restore Customer

Restore a soft-deleted customer.

curl -X PUT https://api.nextroute.app/api/customers/cus_abc123/restore \
  -H "Authorization: Bearer YOUR_TOKEN"

GDPR Data Export

Export all data associated with a customer (properties, invoices, payments, service history, communications, referrals, vacation holds, service skips).

curl https://api.nextroute.app/api/customers/cus_abc123/export \
  -H "Authorization: Bearer YOUR_TOKEN"

GDPR Deletion

Anonymize a customer's PII while preserving financial records for compliance.

curl -X DELETE https://api.nextroute.app/api/customers/cus_abc123/gdpr-delete \
  -H "Authorization: Bearer YOUR_TOKEN"

This sets the customer name to "Deleted User", nulls email/phone, and removes property addresses and coordinates.

Check Duplicates

Check for potential duplicate customers by email or address before creating a new record.

curl "https://api.nextroute.app/api/customers/check-duplicate?email=john@example.com&address=123+Main+St" \
  -H "Authorization: Bearer YOUR_TOKEN"

Response:

{
  "duplicate": true,
  "matches": [
    { "id": "cus_abc123", "name": "John Doe", "email": "john@example.com", "address": "123 Main St" }
  ]
}