EcoService OS

EcoService OS Booking API

A multi-tenant REST API any AI voice agent, chatbot or partner app can call to schedule field-service work. Every response carries a request_id, and every customer-facing response carries a voice_speak sentence your agent can read aloud verbatim.

Authentication

Send your tenant key as Authorization: Bearer esk_live_… (or X-API-Key). Keys are scoped per capability and optionally per brand, rate limited to 60 requests per minute, and issued from Workspace → Booking API keys. Base URL: https://ecoserviceos.ecopowerhub.ai/api/public/v1 (the shorthand /v1/… also works).

Endpoints

MethodPathSummaryScope
GET/v1/healthLiveness probe (no auth)
GET/v1/meTenant profile, timezone, service ZIPsany
GET/v1/job-typesBookable job types for a brandavailability:read
POST/v1/customers/upsertMatch by phone, then emailcustomers:write
GET/v1/availabilityUp to 8 arrival windowsavailability:read
POST/v1/bookingsCreate a booking or emergency requestbookings:write
GET/v1/bookingsList bookingsbookings:read
GET/v1/bookings/{id}Fetch one bookingbookings:read
POST/v1/bookings/{id}/cancelCancel a bookingbookings:write
POST/v1/bookings/{id}/notifyQueue confirmation / reminderbookings:write
POST/v1/leadsCapture an out-of-area or non-truck leadbookings:write

Offer windows

curl -s https://ecoserviceos.ecopowerhub.ai/api/public/v1/availability \
  -H "Authorization: Bearer esk_live_..." \
  -G --data-urlencode "brand=ecoservice_os" \
     --data-urlencode "job_type=appliance-repair" \
     --data-urlencode "zip=21201"

Book the window

Send an Idempotency-Key (the call id works well) so a retried request replays the same booking instead of creating a second truck roll.

curl -s -X POST https://ecoserviceos.ecopowerhub.ai/api/public/v1/bookings \
  -H "Authorization: Bearer esk_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: call_8837" \
  -d '{
    "brand": "ecoservice_os",
    "job_type": "appliance-repair",
    "window_start": "2026-09-02T12:00:00Z",
    "appliance": "refrigerator",
    "symptom": "not cooling",
    "consent_sms": true,
    "source": "voice_agent",
    "customer": {
      "name": "Dana Reed",
      "phone": "+14105550101",
      "address_line1": "18 Charles St",
      "city": "Baltimore",
      "state": "MD",
      "zip": "21201"
    }
  }'

Voice contract

  • voice_speak is always a single spoken sentence — read it verbatim.
  • OUT_OF_AREA → offer to capture a lead via POST /v1/leads.
  • SLOT_TAKEN → re-call /v1/availability and offer the next two windows.
  • MISSING_PHONE / MISSING_ADDRESS → ask for exactly the missing field.
  • Emergencies never book a window; they return status requested and fire the booking.emergency webhook.

Agent tool template

Paste into Retell, Vapi, ElevenLabs or an OpenAI function-tool definition.

{
  "name": "check_availability",
  "description": "Get up to 8 arrival windows for a service brand, job type and ZIP code.",
  "url": "https://ecoserviceos.ecopowerhub.ai/api/public/v1/availability",
  "method": "GET",
  "headers": { "Authorization": "Bearer {{ECOSERVICE_API_KEY}}" },
  "parameters": {
    "type": "object",
    "required": ["brand", "job_type", "zip"],
    "properties": {
      "brand": { "type": "string", "enum": ["ecoservice_os","fixgrid","repair","academy","diy","sales"] },
      "job_type": { "type": "string" },
      "zip": { "type": "string" }
    }
  },
  "speak_field": "voice_speak"
}

Webhooks

Events: booking.created, booking.booked, booking.emergency, booking.canceled, lead.created. Each delivery is signed with HMAC-SHA256 over `${timestamp}.${rawBody}` and sent as x-ecoservice-signature: sha256=<hex>.