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:

{
  "statusCode": 400,
  "name": "BadRequestError",
  "message": "Missing required parameter: ServiceId",
  "errors": [
    {
      "field": "ServiceId",
      "message": "ServiceId is required"
    }
  ]
}
  • statusCode: HTTP status code indicating error type
  • name: Error class name for programmatic handling
  • message: Human-readable description
  • errors: Array of validation errors (when applicable)

HTTP Status Codes

400 Bad Request

The request is malformed or missing required parameters.

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

Example:

{
  "statusCode": 400,
  "name": "BadRequestError",
  "message": "Invalid date format. Use ISO 8601 or YYYY-MM-DD",
  "errors": [
    {
      "field": "startDate",
      "message": "Invalid date format"
    }
  ]
}

How to fix:

  • Verify all required parameters are present
  • Check parameter types match API schema
  • Validate date strings follow ISO 8601 format
  • 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:

{
  "statusCode": 401,
  "name": "UnauthorizedError",
  "message": "Invalid or expired access token"
}

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:

{
  "statusCode": 403,
  "name": "ForbiddenError",
  "message": "You do not have permission to manage this resource"
}

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 requested resource doesn't exist or has been deleted.

Common causes:

  • Invalid UUID in URL path
  • Resource was soft-deleted (archived)
  • Typo in endpoint URL
  • Resource belongs to different company

Example:

{
  "statusCode": 404,
  "name": "NotFoundError",
  "message": "Document not found"
}

How to fix:

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

422 Unprocessable Entity

The request is well-formed but fails business logic validation.

Common causes:

  • Appointment slot is no longer available
  • Time slot conflicts with existing booking
  • Duration doesn't align with service configuration
  • Resource not linked to requested service
  • Date/time is in the past
  • Booking exceeds configured limits

Example:

{
  "statusCode": 422,
  "name": "UnprocessableEntityError",
  "message": "The selected time slot is not available. Another appointment may have been booked.",
  "errors": [
    {
      "field": "Unavailability.startTime",
      "message": "Time slot conflicts with existing appointment"
    }
  ]
}

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:

{
  "statusCode": 500,
  "name": "InternalServerError",
  "message": "Something went wrong"
}

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:

{
  "statusCode": 400,
  "name": "BadRequestError",
  "message": "Validation failed",
  "errors": [
    {
      "field": "Customer.email",
      "message": "Invalid email format"
    },
    {
      "field": "duration",
      "message": "Duration must be greater than 0"
    }
  ]
}

Each error in the errors array specifies:

  • field: Dot-notation path to the invalid field (e.g., Customer.email, Unavailability.startTime)
  • message: 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 422, 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, 422 (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."
422 Unprocessable Entity (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 422 - invalid business logic
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: