NAV Navbar
Examples

Introduction

Welcome to the Solvice API! You can use our API to access Solvice API endpoints, which can get information on your solved jobs, their statuses and of course post new solve jobs.

Authentication

# With shell, you can just pass the correct header with each request
curl "https://api.solvice.io/"
  -H "Authorization Basic: key"

Make sure to replace key with your API key.

Currently Basic Auth is used for authenticating users. Classically you can add a HTTP header:

"Authorization Basic" + btoa(USERNAME + ":" + PASSWORD)

Getting started

Test our API in just one command

curl https://demo:[email protected]/demo/shift | \
curl https://demo:[email protected]/v1/solve  \
     -X POST -H "Content-Type: application/json" -d @-

You can copy and paste the above in your terminal for a working example. The example uses a randomly generated shift problem.

The Solvice API is super simple! Basically, it holds one /solve endpoint for sending a solve request to for a certain optimization problem and it holds one /jobs/:job_id endpoint for retrieving the solved job asynchronous. That's it! The only thing you have to manage is the actual payload for the solve request.

Solvice API

Common usage of the Solvice API follows this flow:

  1. Post solve request for x seconds
  2. Wait x seconds
  3. Fetch status of job
  4. Fetch solution if status=SOLVED
  5. Fetch statistics if !score.feasible

Solve endpoint

Response example

{
  "id": "job_id",
  "solver": "VRP",
  "solve_duration": 100,
  "status": "QUEUED"
}

Solving a new job is as simple as making a POST request to the solve endpoint.

HTTP request

POST https://api.solvice.io/v1/solve

The payload of the request is the structure defined in the next chapter.

Jobs endpoint

Response example

{
  "id": "job_id",
  "solver": "VRP",
  "solve_duration": 100,
  "status": "QUEUED"
}

When posting a new solve request, this job can be checked again under this endpoint. In fact, it should be the entire request posted as-is.

HTTP request

GET https://api.solvice.io/v1/jobs/{job_id}

Job attributes:

Parameter Description
id The id of the job
solver Type of the solver used for this job
solve_duration How long will the solver take to solve it (in minutes)
status Status of the job

Status endpoint

Response example

{
  "id": "job_id",
  "solver": "VRP",
  "solve_duration": 100,
  "status": "SOLVING"
}

After a specified solve_duration, it is time to check the status of the job. Recurrent polling of the status should be done on this endpoint.

HTTP request

GET https://api.solvice.io/v1/jobs/{job_id}/status

Solution endpoint

Response example

{
  "id": "job_id",
  "solver": "VRP",
  "solve_duration": 100,
  "status": "SOLVED",
  "solution": {...}
}

Once the status is SOLVED, you can get the resulting solution in the Solution endpoint.

HTTP request

GET https://api.solvice.io/v1/jobs/{job_id}/solution

Statistics endpoint

Response example

{
  "id": "job_id",
  "goals": [
    {

    },
    ...

  ]
}

Want to know how it is optimised? This endpoint lets you know what rules have been overruled.

HTTP request

GET https://api.solvice.io/v1/stats/{job_id}

Evaluate endpoint

Response example

{
  "id": "job_id",
  "score": {
       "initScore": -17,
       "hardScore": -600,
       "mediumScore": 0,
       "softScore": -2683,
       "feasible": false,
       "solutionInitialized": false
   },
   "unresolved": [
       {
           "name": "Over Capacity",
           "value": -50,
           "level": "HARD"
       },
       ...
   ],
  "solver": "VRP",
  "solve_duration": 100,
  "status": "SOLVED"
}

The (synchronous) evaluate endpoint allows the user to evaluate an existing solution. Either an historical period or a new manual plan can be evaluated using the same rules and constraints as our api uses to construct an optimized plan. The score object in the return provides details on these constraints and the cost functions. The "initScore" attribute is to be ignored. The model, sent to this endpoint, needs to include the solution (i.e. the ShiftAssignments), in the same format as a return from the /solve endpoint would.

HTTP request

POST https://api.solvice.io/evaluate

Example test workflow

The user can easily test the evaluate endpoint using the following sequence of requests:

GET /demo/shift
POST /solve (include return from /demo/shift in POST, store {job_id})
GET jobs/{job_id}
POST /evaluate (include return from jobs/{job_id})

Shift Schedule

You can explore our API in Postman, by using the following button:

Run in Postman

Shift scheduling is about fairly distributing shifts among employees according to capacity requirements, specialism constraints, preferences, shift types and CAO agreements.

{
  "solver": "SHIFT",
  "demand": [ ... ],
  "employees": [ ... ],
  "options": {
    "shiftBlocksPerDay": 24
  }
}

The structure of a basic workforceplanning model is as follows:

Property Value
demand Array of Shift Demands
statutes Array of Statutes
employees Array of Employees
options A list of options for the scheduling problem

Shift Demands

{
  "shift": {
    ...
  },
  "skill": "Kitchen"
  "prefDemand": 2,
  "minDemand": 1,
  "maxDemand": 3
}

The list of shift demands represents the workstation/skill shift blocks to which it is required/necessary to assign (an) employee(s).

Property Value Description Required
shift Shift Block the shift block object Required
skill String the skill/workstation Required
prefDemand Integer the preferred demand for that shift block Required
minDemand integer the minimal demand for that shift block Optional
maxDemand integer the maximal demand for that shift block Optional

Shift Blocks

{
  "date": "2018-11-14",
  "index": 0,
}

A shift block object consists of a date and a unique index for that block on that date. In combination with the number of shift blocks per day (see: Options), the user has full control of the detail/granularity of the demand profile that can be modeled.

Property Value Description Required
date String the date of the shift block (in "YYYY-MM-DD") Required
index Integer the index of the shift block Required

Statutes

{
  "name": "FIX",
  "minShiftLength": 3,
  "maxShiftLength": 11,
  "minRestBetweenShifts": 12,
  "maxConsecutiveWorkDays": 6,
  "maxHrsPerWeek": 50,
  "minHrsPerWeek": 10,
  "shiftStart": 0.0,
  "latestShiftStart": 24.0,
  "shiftEnd": 22.0,
  "minHoursMonth": 100,
  "maxHoursMonth": 200,
  "overTimeThreshold1": 9.0,
  "overTimeRaise1": 1.2,
  "overTimeThreshold2": 11.0,
  "overTimeRaise2": 1.5,
  "overTimeWeeklyThreshold1": 38,
  "overTimeWeeklyRaise1": 1.5,
  "nightlyThreshold1": 20.0,
  "nightlyRaise": 1.5
}

The list of statutes contain CAO specific parameters and the information with respect to the renumeration of the employees.

Property Value Description Required
name String the name of a statues: e.g. "FIX", "PARTTIME", "STUDENT", ... Required
minShiftLength Integer The minimum number of hours in a shift for an employee Required
maxShiftLength Integer The maximum number of hours in a shift for this employee Required
minRestBetweenShifts Integer The minimum duration (in hours) of a rest period between two shifts for this employee Required
maxConsecutiveWorkDays Integer The maximum days consecutive that this employee can be working Required
maxHrsPerWeek Integer The maximum number of hours this employee can be working in a week Required
minHrsPerWeek Integer The minimum number of hours this employee should be working in a week Required
shiftStart Double The earliest this employee can start working (expressed as decimal in 24 hour-format) Required
latestShiftStart Double The latest this employee can start working (expressed as decimal in 24 hour-format) Required
shiftEnd Double The latest this employee can work on a day (expressed as decimal in 24 hour-format) Required
minHoursMonth Integer The minimum hours per month this employee should be working Required
maxHoursMonth Integer The maximum hours per month this employee should be working Required
overTimeThreshold1 Double The first time threshold for overtime (expressed as decimal in 24 hour-format) Required
overTimeRaise1 Double The raise after the first time threshold for overtime (e.q. 1.2 means a 20% raise per hour) Required
overTimeThreshold2 Double The second time threshold for overtime (expressed as decimal in 24 hour-format) Required
overTimeRaise2 Double The raise after the second time threshold for overtime (e.q. 1.2 means a 20% raise per hour) Required
overTimeWeeklyThreshold1 Integer The number of hours per week after which a "weekly overtime" raise should be given Required
overTimeWeeklyRaise1 Double The weekly overtime raise (e.q. 1.2 means a 20% raise per hour) Required
nightlyThreshold1 Double The time threshold to be considered for a night raise (expressed as decimal in 24 hour-format) Required
nightlyRaise Double The raise after the first time threshold for overtime (e.q. 1.2 means a 20% raise per hour) Required

Employees

{
  "name": "E0",
  "statute": "FIX",
  "skill": [
    "Kitchen",
    "Restaurant",
  ],
  "hourlyPay": 11,
  "efficiency": 1,
  "preferences": [
        {
          "start": "2019-08-09T18:00:00",
          "end": "2019-08-10T02:00:00"
        }
      ],
  "hoursWorkedThisMonth": 0,
  "lastRestDate": "2019-03-04"
}

The employees to assign to the shift block demands are defined as follows.

Property Value Description Required
name String Employee name or reference Required
statute String The statute of the employee Required
skill Array of Strings The skills/workstations this employee can man Required
hourlyPay Double The hourly wage for the employee Required
efficiency Double The efficiency of the employee: e.g. two new employees (efficiency: 0.5) are needed to replace an employee with more experience Required
preferences Array of shift preference objects The preferred working hours for this employee.
hoursWorkedThisMonth Integer The number of hours this employee has already worked this month Required
lastRestDate Date The date of last 36-hour rest period for this employee (in "YYYY-MM-DD") Required

Shift preferences

The shift preferences for the employees can be submitted using shift preference objects:

Property Value Description Required
start LocalDateTime The start of the preferred shift Required
end LocalDateTime The end of the preferred shift Required

Assignments

Assignments can be submitted in the solve request to the workforceplanning model for different reasons:

 {
  "id": 1,
  "date": "2019-03-07",
  "employee": "E0",
  "skill": "Restaurant",
  "startDateTime": "2019-03-07T00:00:00",
  "endDateTime": "2019-03-07T21:00:00",
  "locked": true,
  "countAsWorkingHours": false,  
  "costs": { ... }
}
Property Value Description Required for Input
id Integer A unique identifier for the assignment Required
date LocalDate The date of the assignment. Required
employee String The name of the assigned employee Required
skill String The skill/workstation this employee is assigned to Required
start Integer The starting shiftblock Required
duration Integer The duration, expressed in shiftblocks Required
startDateTime LocalDateTime The starting hour for the assignment Optional
endDateTime LocalDateTime The end hour for the assignment Optional
locked Boolean If this assignment is locked for the optimization or not. Optional
countAsWorkingHours Boolean If this assignment should be included in working hours per week/ month etc. constraints. Optional
costs Costs The cost object associated with this assignment (see under) Optional

Solution

{
  "E0": [
    {
      "date": "2018-11-14",
      "index": 4
    },
    {
      "date": "2018-10-14",
      "index": 5
    },
    {
      "date": "2018-10-14",
      "index": 6
    }
  ],   
  "E1": [
    {
      "date": "2018-11-14",
      "index": 8
    }
  ]
}

When the problem is solved, the solution object returns the assigned Timeblocks per employee. The assignments can also be found in the ShiftAssignments object. The assignment submitted in the solve request (if any) will be added to the ones constructed to solve the problem. Once solved, The following objects can also be retrieved from the Employees object:

In addition, an aggregate Costs object can also be retrieved from the json, combining the costs of all employees.

Hours

{
  "hours": 12,
  "nightTimeHours": 2.5,
  "overTime1Hours": 0,
  "overTime2Hours": 0,
  "weeklyOverTimeHours": 0
}
Property Value Description
hours Double The total number of hours assigned to this employee this planning period
nightTimeHours Double The number of hours, after the night threshold, assigned to this employee this planning period
overTime1Hours Double The number of hours, after the first daily overtime threshold, assigned to this employee this planning period
overTime2Hours Double The number of hours, after the second daily overtime threshold, assigned to this employee this planning period
weeklyOverTimeHours Double The number of hours, after the weekly overtime threshold, assigned to this employee this planning period

Costs

{
  "hourCost": 132,
  "nightTimeCost": 13.75,
  "overTime1Cost": 0,
  "overTime2Cost": 0,
  "weeklyOverTimeCost": 0
}
Property Value Description
hourCost Double The hour cost for this employee this planning period (excl. overtime, nightime, ...)
nightTimeCost Double The cost associated with the hours, after the night threshold, for this employee this planning period
overTime1Cost Double The cost associated with the hours, after the first daily overtime threshold, for this employee this this planning period
overTime2Cost Double The cost associated with the hours, after the second daily overtime threshold, for this employee this this planning period
weeklyOverTimeCost Double The cost associated with the hours, after the weekly overtime threshold, for this employee this this planning period

options

{
  "shiftBlocksPerDay": 24,
  "includeShiftPreferences:": false  
}

The definition of the options.

Property Value Description Required
shiftBlocksPerDay Integer The number of blocks in a day Required
includeShiftPreferences Boolean Whether the shift preferences should be accommodated maximally optional
startDate Date A reference date for this planning period optional

Errors

Message structure

For debugging purposes, we identify two types of errors that can occur when sending bad requests. This will help the developer integrating the Solvice API to determine whether

JSON error:

Property Description
errorCode The exact code of the error
explanation Description of the error
line Line number of the error
column Column number of the error

Validation error:

Property Description
errorCode The exact code of the error
explanation Description of the error
propertyPath Path of the property that has a validation error

Codes

The Solvice API uses the following error codes:

Error Code Error Name Description
400 Bad Request Your request is wrong. Check specific reasons.
401 Unauthorized Your API key is wrong.
403 Forbidden The request is for administrators only.
404 Not Found The specified resource could not be found.
405 Method Not Allowed You tried to access a resource with an invalid method.
406 Not Acceptable You requested a format that isn't JSON.
429 Too Many Requests You're requesting too many solve requests! Slow down!
500 Internal Server Error We had a problem with our server. Try again later.
503 Service Unavailable We're temporarily offline for maintenance. Please try again later.