Using provisioning to create multiple user accounts

Provisioning user records en mass asynchronously using JSON or CSV.

Skedulo supports bulk resource provisioning either by sending the data directly to an endpoint as a JSON array or by importing the user information as a JSON or CSV file via a cURL command to another endpoint.

This allows you to use your existing user data to quickly create a large number of resource profiles in your Skedulo account.

The /onboarding/provision endpoints import user data from your file, adds their credentials to Auth0 and sends out the Skedulo onboarding email to their provided email address.

Prerequisite

The examples in this section use jq to format JSON responses to cURL requests in a more readable format, but it is not essential.

The examples use $AUTH_TOKEN to represent your API token. We recommend that you set your API token an environment variable either locally or in your preferred REST API client.

Provisioning users in a REST API request body

You can provision a user, or users, by sending the JSON data for the profile you want to create directly to the /onboarding/provision/standalone/users/bulk endpoint using the POST method.

1 . Provision users directly with a JSON array sent directly to the /onboarding/provision/standalone/users/bulk endpoint.

The following example request creates two new user profiles:

* `Admin User` with both `Scheduler` and `Administrator` roles.
* `NewResource User` with the `Resource` role.
curl --request POST \
  --url https://api.skedulo.com/onboarding/provision/standalone/users/bulk \
  --header 'authorization: Bearer $AUTH_TOKEN' \
  --header 'content-type: application/json' \
  --data '[
	{
		"firstName": "Admin",
		"lastName": "User",
		"email": "gemma+test701@skedulo.com",
		"sendInvitation": true,
		"roles": [
			"Administrator",
			"Scheduler"
		]
	},
	{
		"firstName": "NewResource",
		"lastName": "User",
		"email": "ghilton+test702@skedulo.com",
		"sendInvitation": true,
		"roles": [
			"Resource"
		],
		"resource": {
			"primaryRegionId":"00038151-967b-41bb-847f-b84393b4894b",
			"isActive": true
			}
	}
]'

If the request is successful, the response looks something like this:

{
  "result": {
    "taskId": 85,
    "tenantId": "sk_1d8b120bc51d4ce7af222bd63f385155",
    "type": "bulk_user_import",
    "createdAt": "2019-09-26T04:46:43.011418Z",
    "lastCheckedInAt": null,
    "completedAt": null,
    "success": true,
    "errorMsg": null
  }
}

2 . You can check the status of your resource provisioning request using a GET request that references the taskId:

{
  "result": {
    "task": {
      "taskId": 85,
      "tenantId": "sk_1d8b120bc51d4ce7af222bd63f385155",
      "type": "bulk_user_import",
      "createdAt": "2019-09-26T04:46:43.011418Z",
      "lastCheckedInAt": "2019-09-26T04:46:46.021069Z",
      "completedAt": "2019-09-26T04:46:46.873375Z",
      "success": true,
      "errorMsg": null
    },
    "users": [
      {
        "email": "gemma+test701@skedulo.com",
        "taskId": 85,
        "firstName": "Admin",
        "lastName": "User",
        "success": true,
        "errorMsg": null
      },
      {
        "email": "ghilton+test702@skedulo.com",
        "taskId": 85,
        "firstName": "NewResource",
        "lastName": "User",
        "success": true,
        "errorMsg": null
      }
    ]
  }
}

The response shows that both resources were created successfully and also includes timestamps for the request and its completion.

Provisioning users from a JSON file

You can provision users from a JSON file by sending the file in a cURL request to the /onboarding/provision/standalone/users/file endpoint.

Using a JSON or CSV file to provision resources is useful where you have a significant number of users that you want to create en mass in your Skedulo account.

1 . Create your JSON file.

The following is an example of a JSON file called test.json, which includes five resources that we are going to create in the Skedulo application:

[
	{
		"firstName": "Resource1",
		"lastName": "User",
		"email": "ghilton+test40@skedulo.com",
		"sendInvitation": true,
		"roles": [
			"Resource"
		],
		"resource": {
			"primaryRegionId":"00038151-967b-41bb-847f-b84393b4894b",
			"isActive": true
		}
	},
	{
		"firstName": "Resource2",
		"lastName": "User",
		"email": "ghilton+test41@skedulo.com",
		"sendInvitation": true,
		"roles": [
			"Resource"
		],
		"resource": {
			"primaryRegionId":"00038151-967b-41bb-847f-b84393b4894b",
			"isActive": true
		}
	},
	{
		"firstName": "Resource3",
		"lastName": "User",
		"email": "ghilton+test42@skedulo.com",
		"sendInvitation": true,
		"roles": [
			"Resource"
		],
		"resource": {
			"primaryRegionId":"00038151-967b-41bb-847f-b84393b4894b",
			"isActive": true
		}
	},
	{
		"firstName": "Resource4",
		"lastName": "User",
		"email": "ghilton+test43@skedulo.com",
		"sendInvitation": true,
		"roles": [
			"Resource"
		],
		"resource": {
			"primaryRegionId":"00038151-967b-41bb-847f-b84393b4894b",
			"isActive": true
		}
	},
	{
		"firstName": "Resource5",
		"lastName": "User",
		"email": "ghilton+44@skedulo.com",
		"sendInvitation": true,
		"roles": [
			"Resource"
		],
		"resource": {
			"primaryRegionId":"00038151-967b-41bb-847f-b84393b4894b",
			"isActive": true
		}
	}
]

2 . Using cURL, send this file to the /onboarding/provision/standalone/users/file endpoint.

curl -s -H "Authorization: Bearer $AUTH_TOKEN" -F "source=@test.json;type=application/json" https://api.skedulo.com/onboarding/provision/standalone/users/file | jq 

The successful JSON response in the terminal provides a taskId:

{
	"result": {
		"taskId": 76,
		"tenantId": "sk_1d8b120bc51d4ce7af222bd63f385155",
		"type": "bulk_user_import",
		"createdAt": "2019-09-20T06:12:22.994863Z",
		"lastCheckedInAt": null,
		"completedAt": null,
		"success": true,
		"errorMsg": null
	}
}

3 . Check the status of your request using a GET request including the taskId:

curl --request GET \
  --url https://api.skedulo.com/onboarding/provision/standalone/users/bulk/76 \
  --header 'authorization: Bearer $AUTH_TOKEN' \
  --header 'content-type: application/json'

This provides a status update for each of the users included in the JSON file. In this case, they have all been created with no errors:

{
  "result": {
    "task": {
      "taskId": 76,
      "tenantId": "sk_1d8b120bc51d4ce7af222bd63f385155",
      "type": "bulk_user_import",
      "createdAt": "2019-09-20T06:12:22.994863Z",
      "lastCheckedInAt": "2019-09-20T06:17:14.645193Z",
      "completedAt": "2019-09-20T06:17:15.889724Z",
      "success": true,
      "errorMsg": null
    },
    "users": [
      {
        "email": "ghilton+44@skedulo.com",
        "taskId": 76,
        "firstName": "Resource5",
        "lastName": "User",
        "success": true,
        "errorMsg": null
      },
      {
        "email": "ghilton+test40@skedulo.com",
        "taskId": 76,
        "firstName": "Resource1",
        "lastName": "User",
        "success": true,
        "errorMsg": null
      },
      {
        "email": "ghilton+test41@skedulo.com",
        "taskId": 76,
        "firstName": "Resource2",
        "lastName": "User",
        "success": true,
        "errorMsg": null
      },
      {
        "email": "ghilton+test42@skedulo.com",
        "taskId": 76,
        "firstName": "Resource3",
        "lastName": "User",
        "success": true,
        "errorMsg": null
      },
      {
        "email": "ghilton+test43@skedulo.com",
        "taskId": 76,
        "firstName": "Resource4",
        "lastName": "User",
        "success": true,
        "errorMsg": null
      }
    ]
  }
}

Provisioning users from a CSV file

You can also provision multiple resources using a CSV file by sending the file to the same /onboarding/provision/standalone/users/file endpoint.

This allows you to quickly create user profiles using data from your other systems (such as a payroll system or other employee database).

The following procedure uses an example CSV file that creates 10 new user profiles in Skedulo with Administrator, Scheduler, and Resource roles.

1 . Create a CSV file containing the user profile information for the resources you want to provision in Skedulo:

UID,firstName,lastName,email,sendInvitation,roles,resource__primaryRegionId,resource__resourceType,resource__employmentType,resource__isActive,resource__category,resource__homeAddress,resource__mobilePhone,resource__countryCode,resource__notificationType,resource__workingHourType,resource__geoLongitude,resource__geoLatitude
,CSV,Test1,ghilton+test4@skedulo.com,true,"[""Administrator"",""Scheduler"",""Resource""]",00038151-967b-41bb-847f-b84393b4894b,Person,Full-time,TRUE,Customer Service,"46 Warner St, Fortitude Valley, QLD 4006",0408 790 664,AU,sms,Availability,60,60
,CSV,Test2,ghilton+test5@skedulo.com,true,"[""Administrator"",""Scheduler"",""Resource""]",00038151-967b-41bb-847f-b84393b4894b,Person,Full-time,TRUE,Customer Service,"46 Warner St, Fortitude Valley, QLD 4006",0408 790 664,AU,sms,Availability,60,60
,CSV,Test3,ghilton+test6@skedulo.com,true,"[""Administrator"",""Scheduler"",""Resource""]",00038151-967b-41bb-847f-b84393b4894b,Person,Full-time,TRUE,Customer Service,"46 Warner St, Fortitude Valley, QLD 4006",0408 790 664,AU,sms,Availability,60,60
,CSV,Test4,ghilton+test7@skedulo.com,true,"[""Administrator"",""Scheduler"",""Resource""]",00038151-967b-41bb-847f-b84393b4894b,Person,Full-time,TRUE,Customer Service,"46 Warner St, Fortitude Valley, QLD 4006",0408 790 664,AU,sms,Availability,60,60
,CSV,Test5,ghilton+test8@skedulo.com,true,"[""Administrator"",""Scheduler"",""Resource""]",00038151-967b-41bb-847f-b84393b4894b,Person,Full-time,TRUE,Customer Service,"46 Warner St, Fortitude Valley, QLD 4006",0408 790 664,AU,sms,Availability,60,60
,CSV,Test6,ghilton+test9@skedulo.com,true,"[""Administrator"",""Scheduler"",""Resource""]",00038151-967b-41bb-847f-b84393b4894b,Person,Full-time,TRUE,Customer Service,"46 Warner St, Fortitude Valley, QLD 4006",0408 790 664,AU,sms,Availability,60,60
,CSV,Test7,ghilton+test10@skedulo.com,true,"[""Administrator"",""Scheduler"",""Resource""]",00038151-967b-41bb-847f-b84393b4894b,Person,Full-time,TRUE,Customer Service,"46 Warner St, Fortitude Valley, QLD 4006",0408 790 664,AU,sms,Availability,60,60
,CSV,Test8,ghilton+test11@skedulo.com,true,"[""Administrator"",""Scheduler"",""Resource""]",00038151-967b-41bb-847f-b84393b4894b,Person,Full-time,TRUE,Customer Service,"46 Warner St, Fortitude Valley, QLD 4006",0408 790 664,AU,sms,Availability,60,60
,CSV,Test9,ghilton+test12@skedulo.com,true,"[""Administrator"",""Scheduler"",""Resource""]",00038151-967b-41bb-847f-b84393b4894b,Person,Full-time,TRUE,Customer Service,"46 Warner St, Fortitude Valley, QLD 4006",0408 790 664,AU,sms,Availability,60,60
,CSV,Test10,ghilton+test13@skedulo.com,true,"[""Administrator"",""Scheduler"",""Resource""]",00038151-967b-41bb-847f-b84393b4894b,Person,Full-time,TRUE,Customer Service,"46 Warner St, Fortitude Valley, QLD 4006",0408 790 664,AU,sms,Availability,60,60

The resource__isActive field is included in the example file above however, unlike user provisioning from a JSON file, the isActive field is not required when provisioning users from a CSV file.

2 . Send the file to the /onboarding/provision/standalone/users/file endpoint using a cURL request:

curl -s -H "Authorization: Bearer $DEV_TOKEN" -F "source=@test.csv;type=text/csv" https://api.skedulo.com/onboarding/provision/standalone/users/file | jq

The successful operation returns the following response:

{
  "result": {
    "taskId": 36,
    "tenantId": "sk_1d8b120bc51d4ce7af222bd63f385155",
    "type": "bulk_user_import",
    "createdAt": "2019-09-20T01:23:56.653230Z",
    "lastCheckedInAt": null,
    "completedAt": null,
    "success": true,
    "errorMsg": null
  }
}

3 . Check the status of the resource provisioning operation by using a GET request that references the taskId:

curl --request GET \
  --url https://api.skedulo.com/onboarding/provision/standalone/users/bulk/36 \
  --header 'authorization: Bearer $AUTH_TOKEN' \
  --header 'content-type: application/json'

The successful response shows all 10 resource request jobs completed:

{
  "result": {
    "task": {
      "taskId": 36,
      "tenantId": "sk_1d8b120bc51d4ce7af222bd63f385155",
      "type": "bulk_user_import",
      "createdAt": "2019-09-20T01:23:56.653230Z",
      "lastCheckedInAt": "2019-09-20T01:27:04.824804Z",
      "completedAt": "2019-09-20T01:27:06.138906Z",
      "success": true,
      "errorMsg": null
    },
    "users": [
      {
        "email": "ghilton+test10@skedulo.com",
        "taskId": 36,
        "firstName": "CSV",
        "lastName": "Test7",
        "success": true,
        "errorMsg": null
      },
      {
        "email": "ghilton+test11@skedulo.com",
        "taskId": 36,
        "firstName": "CSV",
        "lastName": "Test8",
        "success": true,
        "errorMsg": null
      },
      {
        "email": "ghilton+test12@skedulo.com",
        "taskId": 36,
        "firstName": "CSV",
        "lastName": "Test9",
        "success": true,
        "errorMsg": null
      },
      {
        "email": "ghilton+test13@skedulo.com",
        "taskId": 36,
        "firstName": "CSV",
        "lastName": "Test10",
        "success": true,
        "errorMsg": null
      },
      {
        "email": "ghilton+test4@skedulo.com",
        "taskId": 36,
        "firstName": "CSV",
        "lastName": "Test1",
        "success": true,
        "errorMsg": null
      },
      {
        "email": "ghilton+test5@skedulo.com",
        "taskId": 36,
        "firstName": "CSV",
        "lastName": "Test2",
        "success": true,
        "errorMsg": null
      },
      {
        "email": "ghilton+test6@skedulo.com",
        "taskId": 36,
        "firstName": "CSV",
        "lastName": "Test3",
        "success": true,
        "errorMsg": null
      },
      {
        "email": "ghilton+test7@skedulo.com",
        "taskId": 36,
        "firstName": "CSV",
        "lastName": "Test4",
        "success": true,
        "errorMsg": null
      },
      {
        "email": "ghilton+test8@skedulo.com",
        "taskId": 36,
        "firstName": "CSV",
        "lastName": "Test5",
        "success": true,
        "errorMsg": null
      },
      {
        "email": "ghilton+test9@skedulo.com",
        "taskId": 36,
        "firstName": "CSV",
        "lastName": "Test6",
        "success": true,
        "errorMsg": null
      }
    ]
  }
}

Troubleshooting

Email already exists

Users listed in the JSON or CSV file must have a unique email address that does not already exist in the Skedulo system. If an email address is already associated with a Skedulo user, the resource will not be created from the JSON or CSV file and the following error message appears for that user in the task information:

...

"users": [
  {
    "email": "ghilton+44@skedulo.com",
    "taskId": 82,
    "firstName": "Resource5",
    "lastName": "User",
    "success": false,
    "errorMsg": "Email Already Exists"
  }
  ...
]

Incorrect file structure

JSON or CSV files that are not structured correctly or contain errors return the following error message when attempting to upload the file with the cURL command:

{
  "errorType": "invalid_import_data",
  "message": "Invalid Import data: ..."
}

The message field provides information about the error.

Users need resource role

As a minimum, resources provisioned from a CSV file require a valid RegionId. Provisioning resources from a JSON file requires both a valid RegionId, as well as the isActive field (set to true).

Failing to provide this information in the resource file results in the following error message in response to the cURL request:

{
  "errorType": "users_need_resource_role",
  "message": "Users with an assigned resource must have Resource role and vice versa. Email of user records in error: {$email_address}"
}

The message field provides information about the error.

API User not set

The following error occurs if there is no API User set for your organization:

{
  "errorType": "api_user_not_found",
  "message": "API User for tenant sk_00000000aaaaa0000a00 has not been set up.",
  "tenantId": "sk_00000000aaaaa0000a00"
}

You must configure an API User for your organization using the Skedulo web application before you can make API requests.