Quick Start
Three steps from your first API key to a successful response.
Get Your API Key
Navigate to Settings > API Keys in your Exoserva dashboard and generate a new API key.
Make Your First Request
Use your API key to authenticate and make your first API call.
curl -X GET 'https://api.exoserva.com/api/v3/jobs' \
-H 'Authorization: Bearer YOUR_API_KEY'Handle the Response
Parse the JSON response and integrate it into your application.
Authentication
Authenticate API requests with bearer tokens generated in Settings → API Keys.
Bearer Token
Send your API key as a Bearer token in the Authorization header on every request.
Authorization: Bearer YOUR_API_KEYTokens never expire on their own. Rotate them from Settings → API Keys when a team member leaves or a token leaks.
Treat your API key like a password. Never commit it to source control or expose it in client-side bundles.
Security
A/B Testing
A/B test experiments and variant management
Accounts
Customer account management
Agents
AI agent status, configuration, and logs
AI Costs
AI usage cost tracking and budget management
Analytics
Business analytics, reports, and correlations
Authentication
Authentication, login, SSO, and token management
Billing
Subscription billing, plans, seats, and payment methods
Branding
White-label branding, logos, domains, and email templates
Cache
Cache management and invalidation
Calendar
Calendar integrations and scheduling
Contractor Portal
Contractor portal jobs, stats, and actions
Customers
Customer records, notes, and portal access
Dispatch
Dispatch assignments, skills, locations, and notifications
Follow-Ups
Follow-up queue management and automation
Health
Health checks, liveness, and readiness probes
Invoices
Invoice CRUD, actions, payments, and reports
Maintenance Schedules
Preventive maintenance schedules and metrics
Maintenance Templates
Maintenance task templates
Notifications
Notification list, actions, and unread counts
Organizations
Organization hierarchy and management
Payments
Payment processing and records
Portal
Tenant portal auth, work orders, and service requests
PriceBook
Price book items, categories, and materials
QuickBooks
QuickBooks integration and sync
Reports
Business reports and data exports
Safety Standards
Safety standards and OSHA compliance
Schedule
Scheduling slots, optimization, and service durations
Search
Global search across entities
Signatures
Digital signature requests and provider webhooks
Tenants
Tenant (renter) CRUD and actions
Territories
Service territory management and technician assignments
Time Tracking
Time entries, clock in/out, breaks, timesheets, and payroll
Users
User CRUD, roles, preferences, and profile
Vendor Intelligence
AI vendor analysis and insights
Vendor Portal
Vendor self-service portal
Voice
Voice AI settings, calls, and analytics
Webhooks
External webhook integrations (Twilio, Stripe, etc.)
Work Orders
Work order management and SLAs
Workflows
Workflow automation engine
AI
AI Actions
AI Analysis
AI Documentation
AI Emergency Detection
AI Financial
AI Inline
AI Maintenance Triage
AI Models
AI Panels
AI Photo Analysis
AI Predictions
AI Settings
AI Troubleshooting
API Keys
Auth
Batch
Booking
Communication
Conversations
Dashboard
Documents
Email Tracking
Feedback
GBP
Integrations
Inventory
Leases
Mobile
Modules
Onboarding
Phone Provisioning
Predictive
Roles
Routing
Settings
Tasks
Thumbtack
Twilio Phones
Vendor COI
Weather
Yelp
Error Codes
HTTP status codes and the standard error payload returned by every endpoint.
| Code | Status | Description |
|---|---|---|
| 400 | Bad Request | The request was malformed or missing required parameters. |
| 401 | Unauthorized | Authentication credentials are missing or invalid. |
| 403 | Forbidden | You do not have permission to access this resource. |
| 404 | Not Found | The requested resource does not exist. |
| 409 | Conflict | The request conflicts with the current state of the resource. |
| 422 | Unprocessable Entity | The request body failed validation. |
| 429 | Too Many Requests | Rate limit exceeded. Retry after the specified delay. |
| 500 | Internal Server Error | An unexpected error occurred on the server. |
Error Response Format
Each error response carries a stable machine-readable code, a human-readable message, and the failing field path when applicable.
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "The request body failed validation.",
"details": [
{ "field": "email", "message": "Invalid email format" }
]
}
}Rate Limits
Rate limits prevent abuse and ensure consistent performance across all tenants. Limits are per-tenant, per-window.
| Tier | Limit | Window |
|---|---|---|
| Standard | 100 requests | per minute |
| Premium | 500 requests | per minute |
| Enterprise | 2,000 requests | per minute |
Response Headers
Rate-limit state is returned on every response in the headers below. Honour `Retry-After` when you receive a 429.
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1640000000
Retry-After: 60When you receive a 429, sleep for the duration in the `Retry-After` header (seconds) before retrying. Avoid exponential back-off without honouring the hint — it just compounds the throttling window.
Webhooks
Preview of the upcoming outbound-webhook surface. See banner above for current status.
Outbound webhooks aren't live yet
The design below is a preview of the upcoming outbound-webhook surface. The Settings → Integrations webhook configuration UI and the signed-delivery dispatcher are not yet shipped; today these events are emitted internally but no HTTP delivery to your URL is performed. When it ships, this banner disappears.
Setup (planned)
Once shipped, you'll configure a webhook URL in Settings → Integrations. Each delivery will be signed; verify the signature before processing.
Event Catalog (planned)
Payload Shape (planned)
Once outbound delivery is shipped, every webhook will wrap the event-specific payload in the envelope below. The `data` field will carry the entity snapshot at event time.
{
"event": "job.completed",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"id": "job_abc123",
"status": "completed",
"customer_id": "cust_xyz789"
}
}Verification (planned)
Once shipped, compute the HMAC-SHA256 of the raw request body using your webhook secret and compare it to the `X-Exoserva-Signature` header. Reject requests where the signatures do not match.
