Error Codes Reference

Understand OnSched API error responses, status codes, and how to handle common issues in your integration.

Environment tip: All examples use v3.onsched.com for production. Replace the host with api-stage.onsched.com when calling the staging environment.

Error Response Format

OnSched returns structured error responses with HTTP status codes and descriptive messages. All errors follow this format:

{
  "success": false,
  "message": "Missing required parameter: ServiceId",
  "errors": [
    {
      "type": "field",
      "path": "ServiceId",
      "msg": "This field is required"
    }
  ]
}
  • success: always false on an error response
  • message: human-readable description
  • errors: array of field-level validation errors, empty when the failure is not field-specific

Read the HTTP status code from the response itself; it is not repeated in the body.

HTTP Status Codes

400 Bad Request

The request is malformed, references something your company does not have, or is rejected by a booking rule. This is the status for everything about the request payload — 404 is used only when the resource addressed in the URL path does not exist.

Common causes:

  • Missing required query parameters or body fields
  • Invalid data types (e.g., string where UUID expected)
  • Parameter values outside acceptable ranges
  • Date formatting errors
  • A missing path id, such as DELETE /v3/customer/ with no customer id
  • A LocationId, ServiceId, or CustomerId in the body or query string that is not one of your company's records
  • A ResourceIds entry that is not one of your resources, or is not linked to the requested location and service
  • The requested time slot is not available, or the booking violates a configured limit

Example:

{
  "success": false,
  "message": "Invalid date format. Use ISO 8601 or YYYY-MM-DD",
  "errors": [
    {
      "type": "field",
      "path": "startDate",
      "msg": "Invalid date format"
    }
  ]
}

Reference errors name the offending value so you can log or surface it directly:

{
  "success": false,
  "message": "Invalid ResourceIds: resource 0b3a1b2f-2564-4238-b7eb-259e8136bbd0 is not linked to the requested location and service",
  "errors": []
}

How to fix:

  • Verify all required parameters are present
  • Check parameter types match API schema
  • Validate date strings follow ISO 8601 format
  • Confirm the ids you send belong to the authenticated company, and that resources are linked to the location and service you are booking
  • Review the Swagger documentation for endpoint requirements

401 Unauthorized

Authentication credentials are missing, invalid, or expired.

Common causes:

  • Missing Authorization header
  • Expired access token (tokens last one hour)
  • Invalid client credentials
  • Malformed Bearer token

Example:

{
  "success": false,
  "message": "Invalid or expired access token",
  "errors": []
}

How to fix:

  • Request a fresh access token via POST /v3/oauth/token
  • Ensure Authorization: Bearer <token> header is included
  • For dashboard authentication, verify you're including x-api-key and x-client-id headers
  • See Authentication Guide for credential setup

403 Forbidden

You're authenticated but lack permission for the requested resource.

Common causes:

  • Attempting to access another company's data
  • Scope restrictions on OAuth token
  • Accessing disabled or suspended accounts
  • User role lacks necessary permissions

Example:

{
  "success": false,
  "message": "You do not have permission to manage this resource",
  "errors": []
}

How to fix:

  • Verify the resource belongs to your authenticated company
  • Check OAuth scope includes required permissions (read, write)
  • Ensure company and location accounts are not suspended
  • Contact support if role permissions need adjustment

404 Not Found

The record addressed by the URL path doesn't exist or has been deleted — for example GET /v3/appointment/{id} with an unknown id. Ids you send in a body or query string are validated as request data instead and return 400.

Common causes:

  • Unknown UUID in the URL path
  • Record was soft-deleted (archived)
  • Record belongs to a different company
  • Typo in the endpoint URL (unmatched routes also return 404)

Example:

{
  "success": false,
  "message": "Document not found",
  "errors": []
}

How to fix:

  • Double-check UUID values are correct
  • Verify the record hasn't been deleted
  • Ensure endpoint path matches documentation
  • Use GET endpoints to list records and confirm IDs

Business rule rejections

Requests that are well formed but rejected by scheduling rules — slot no longer available, overlapping booking, resource not linked to the requested service, booking limit exceeded — return 400 with a message describing the rule that rejected them. OnSched does not return 422.

Example:

{
  "success": false,
  "message": "The selected time slot is not available.",
  "errors": []
}

How to fix:

  • Call GET /v3/availability before creating appointments
  • Verify selected resources are linked to the service
  • Check service allows requested duration (if using overrideDuration)
  • Ensure booking doesn't violate service limits (see Booking Limits)
  • For rescheduling, confirm new slot passes validation

500 Internal Server Error

An unexpected error occurred on the server.

Common causes:

  • Database connectivity issues
  • External service timeout (e.g., calendar sync)
  • Unhandled edge case in processing

Example:

{
  "success": false,
  "message": "Something went wrong",
  "errors": []
}

How to fix:

  • Retry the request after a brief delay
  • Check service status page for known issues
  • If persistent, contact support with request details (timestamp, endpoint, request ID if available)

Validation Errors

Endpoints that accept structured input return detailed validation errors:

{
  "success": false,
  "message": "Validation Error",
  "errors": [
    {
      "type": "field",
      "location": "body",
      "path": "Customer.email",
      "msg": "Invalid email format"
    },
    {
      "type": "field",
      "location": "query",
      "path": "duration",
      "msg": "Duration must be greater than 0"
    }
  ]
}

Each error in the errors array specifies:

  • path: Dot-notation path to the invalid field (e.g., Customer.email, Unavailability.startTime)
  • location: Where the field was read from — body, query, or params
  • msg: Specific reason the field is invalid

Use these to display inline validation messages in your UI.

Common Scenarios

Availability Check Returns Empty

If GET /v3/availability returns no slots:

  • Service may have no resources assigned at the location
  • Requested date range is outside resource schedules
  • All slots are booked
  • Service duration doesn't fit within operating hours

Not an error: An empty availability response with status 200 is valid—it means no slots are open.

Appointment Creation Fails After Availability Check

Race conditions can occur if another user books the same slot between your availability check and appointment creation.

Best practice:

  1. Show available slots from GET /v3/availability
  2. User selects a slot
  3. Create appointment immediately—if it fails with 400 and a slot-unavailable message, refresh availability and ask user to pick again
  4. Consider using holds (POST /appointment/hold) for multi-step checkouts

Token Expires Mid-Session

OAuth2 tokens last one hour. If you receive 401 errors on long-running sessions:

  • Implement automatic token refresh when 401 is encountered
  • Store token expiration time (expires_in) and proactively refresh before expiry
  • Don't hardcode tokens—request them programmatically

Error Handling Best Practices

Retry Logic

Implement exponential backoff for transient errors:

  • Retry: 500, 503 status codes (server errors)
  • Don't retry: 400, 401, 403, 404, 409 (client errors require fixing the request)

Example retry strategy:

  1. Wait 1 second, retry
  2. If still failing, wait 2 seconds, retry
  3. If still failing, wait 4 seconds, retry
  4. After 3 attempts, show error to user

User-Friendly Messages

Don't expose raw API errors to end users:

API ErrorUser-Friendly Message
401 Unauthorized"Session expired. Please log in again."
404 Not Found"This appointment could not be found. It may have been cancelled."
400 Bad Request (slot conflict)"This time is no longer available. Please choose another slot."
500 Internal Server Error"We're experiencing technical difficulties. Please try again shortly."

Logging

Log all API errors with context for debugging:

  • Request method and URL
  • Request headers (excluding sensitive tokens)
  • Request body
  • Response status and body
  • Timestamp
  • User/session identifier

Webhook Errors

Webhook deliveries don't retry automatically. If your webhook endpoint fails:

  • Return a 2xx status code to acknowledge receipt
  • Process webhook payloads asynchronously to avoid timeouts
  • Log all incoming webhooks for manual reprocessing if needed
  • Monitor webhook endpoint health
  • See Webhook Guide for details

Testing Error Scenarios

Use invalid data to test error handling:

# Test 400 - missing required parameter
curl https://v3.onsched.com/v3/availability \
  -H "Authorization: Bearer YOUR_TOKEN"

# Test 401 - invalid token
curl https://v3.onsched.com/v3/company \
  -H "Authorization: Bearer invalid_token_12345"

# Test 404 - nonexistent resource
curl https://v3.onsched.com/v3/appointment/00000000-0000-0000-0000-000000000000 \
  -H "Authorization: Bearer YOUR_TOKEN"

# Test 400 - rejected by a booking rule (slot in the past)
curl -X POST "https://v3.onsched.com/v3/appointment?LocationId=LOC_ID&ServiceId=SVC_ID" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "Unavailability": {
      "startTime": "2020-01-01T10:00:00Z",
      "endTime": "2020-01-01T10:30:00Z"
    },
    "duration": 30
  }'

Build comprehensive error handling early—it improves user experience and makes debugging easier.

Need Help?

If you encounter errors not covered here:


Did this page help you?