{"_id":"599bcb49c03fa2000f83dbaf","project":"56439dfe9eebf70d00490d54","version":{"_id":"5864d2df79ce642d00f0fec7","project":"56439dfe9eebf70d00490d54","__v":4,"createdAt":"2016-12-29T09:09:51.074Z","releaseDate":"2016-12-29T09:09:51.074Z","categories":["5864d2df79ce642d00f0fec8","5864d2df79ce642d00f0fec9","5864d2df79ce642d00f0feca","5864d2df79ce642d00f0fecb","5864d2df79ce642d00f0fecc","5864d2df79ce642d00f0fecd","5864d2df79ce642d00f0fece","5864d2df79ce642d00f0fecf","5864d2df79ce642d00f0fed0","5864d2df79ce642d00f0fed1","5864d2df79ce642d00f0fed2","5864d2df79ce642d00f0fed3","5864d2df79ce642d00f0fed4","5864d2df79ce642d00f0fed5","5864d2df79ce642d00f0fed6","5864d2df79ce642d00f0fed7","5864d2df79ce642d00f0fed8","5864d2df79ce642d00f0fed9","5864d2df79ce642d00f0feda","5864d2df79ce642d00f0fedb","5864d2df79ce642d00f0fedc","5864d2df79ce642d00f0fedd","5864d2df79ce642d00f0fede","598aa64f4b6e990019b7a2d2","599bc76bc03fa2000f83db2a","599bcc3c3c5bf7000f3434fc"],"is_deprecated":false,"is_hidden":false,"is_beta":true,"is_stable":true,"codename":"","version_clean":"2.0.0","version":"2"},"category":{"_id":"5864d2df79ce642d00f0fedc","version":"5864d2df79ce642d00f0fec7","project":"56439dfe9eebf70d00490d54","__v":0,"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2016-07-18T17:31:42.071Z","from_sync":false,"order":22,"slug":"one-roster","title":"One Roster"},"user":"567b9bf2b56bac0d0019d914","__v":0,"parentDoc":null,"updates":[],"next":{"pages":[],"description":""},"createdAt":"2017-08-22T06:12:25.434Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":0,"body":"[block:api-header]\n{\n  \"title\": \"Authentication for APIs\"\n}\n[/block]\nAll Oneroster APIs are authenticated based on the client id and secret shared by Gooru with partners. Partner need to base64 encode the client id and secret in order to pass as Basic authorization header to APIs.\n\n**Example:** (To generate Base64 Encoded Credentials)\n\nClientId: 3d6bc3ea-2aff-4106-8762-9246d5d84813\nSecret: kteuobYdO1oRfqJ1+PZ5phMSeI=\n\nCombine client id and secret with ‘:’ -\n3d6bc3ea-2aff-4106-8762-9246d5d84813:kteuobYdO1oRfqJ1+PZ5phMSeI= \n\nAnd then encode it by Base64 encoder which will generate string like below. Use it to pass in request header.\nM2Q2YmMzZWEtMmFmZi00MTA2LTg3NjItOTI0NmQ1ZDg0ODEzOmt0ZXVvYllkTzFvUmZxSjErUFo1cGhNU2VJPQ==\n\n[block:api-header]\n{\n  \"title\": \"Upload Roster\"\n}\n[/block]\nThis API is used to upload the roster files in zip format. All csv files contained in the zip should comply to the [IMS Global Oneroster specification](https://www.imsglobal.org/lis/imsOneRosterv1p0/imsOneRosterCSV-v1p0.html). Invalid or extra uploaded files are skipped from rostering. Current scope of this API is to process orgs, users, classes and enrollments only. Other files such as academicSessions, demographics and courses will be not be processed and rostered into system.\n\nAll data will be rostered against the client id (tenant) in Gooru. Client applications need to provide same client id and secret while performing SSO which id used while rostering the users.\n\nThis API will not return any details on error / exceptions for the failed records. Status API should be explicitly called with required parameters to get the status / error while rostering files.\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Name\",\n    \"h-1\": \"Value\",\n    \"0-0\": \"HTTP Method\",\n    \"0-1\": \"POST\",\n    \"1-0\": \"End Point\",\n    \"1-1\": \"http://{host}/api/nucleus-oneroster/{version}/upload\",\n    \"2-0\": \"Sample\",\n    \"2-1\": \"http://oneroster.gooru.org/api/nucleus-oneroster/v1/upload\"\n  },\n  \"cols\": 2,\n  \"rows\": 3\n}\n[/block]\n###Headers\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Header Name\",\n    \"h-1\": \"Value\",\n    \"0-0\": \"Authorization\",\n    \"0-1\": \"Basic <BASE64 ENCODED CREDENTIALS>\",\n    \"1-0\": \"Content-Type\",\n    \"1-1\": \"multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW\"\n  },\n  \"cols\": 2,\n  \"rows\": 2\n}\n[/block]\n  * Replace the correct value of encoded credentials in ‘Authorization’ header\n  * Boundary in the ‘Content-Type’ header is sample. Need to be replaced with actual boundary while calling the API.\n\n###Request Payload\nAttach the file with request.\n\n###Success Reponse\nHTTP Status Code: 201 Created\nLocation header of the response will contain the Upload Id which can be used to get the status of the upload.\n\n\n###Error Response\nIn case of any error while uploading the Roster, API will not provide any details of error / exceptions for records in the files. For Error response codes, refer to Reference section in this document.\n[block:api-header]\n{\n  \"title\": \"Get Upload Status\"\n}\n[/block]\nThis API is used to get the status of the upload for give upload id. For now this API will return total records and success record counts. It may be enhanced in future to return records level details.\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Name\",\n    \"h-1\": \"Value\",\n    \"0-0\": \"HTTP Method\",\n    \"0-1\": \"GET\",\n    \"1-0\": \"End Point\",\n    \"1-1\": \"http://{host}/api/nucleus-oneroster/{version}/upload/{uploadId}/status\",\n    \"2-0\": \"Sample\",\n    \"2-1\": \"http://oneroster.gooru.org/api/nucleus-oneroster/v1/upload/62f3fbd3-4341-4e30-8efe-3b655074133d/status\"\n  },\n  \"cols\": 2,\n  \"rows\": 3\n}\n[/block]\n###Headers\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Header Name\",\n    \"h-1\": \"Value\",\n    \"0-0\": \"Authorization\",\n    \"0-1\": \"Basic <BASE64 ENCODED CREDENTIALS>\"\n  },\n  \"cols\": 2,\n  \"rows\": 1\n}\n[/block]\n  * Replace the correct value of encoded credentials in ‘Authorization’ header. \n\n###Request Payload\nNo request payload required for this API\n\n###Success Response\nHTTP Status Code: 200 OK\n\n###Error Response\nRefer to reference section of this document below.\n\n###Possible Status\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Status\",\n    \"h-1\": \"Purpose\",\n    \"0-0\": \"pending\",\n    \"0-1\": \"Denotes the zip upload is success and pending to be process. The uploads are queued at server and picked up one by one.\",\n    \"1-0\": \"accepted\",\n    \"1-1\": \"Denotes that the upload zip file has been accepted for rostering. This is the status after parsing and validation of all csv files, and still the sync with Gooru main database is pending.\",\n    \"2-0\": \"failed\",\n    \"2-1\": \"Denotes that the upload has been failed. In case of failure while rostering records, this status will be returned.\",\n    \"3-0\": \"completed\",\n    \"3-1\": \"Denotes that the upload has been complete. When all records are rostered successfully, this status will be returned.\"\n  },\n  \"cols\": 2,\n  \"rows\": 4\n}\n[/block]\n##Responses\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n\\t\\\"status\\\": \\\"pending\\\",\\n\\t\\\"total_records\\\": {\\n\\t\\t\\\"orgs\\\": 1,\\n\\t\\t\\\"users\\\": 10,\\n\\t\\t\\\"classes\\\": 2,\\n\\t\\t\\\"enrollments\\\": 12\\n\\t},\\n\\t\\\"success_records\\\": {\\n\\t\\t\\\"orgs\\\": 1,\\n\\t\\t\\\"users\\\": 8,\\n\\t\\t\\\"classes\\\": 2,\\n\\t\\t\\\"enrollments\\\": 10\\n\\t}\\n}\\n\",\n      \"language\": \"json\",\n      \"name\": \"Pending\"\n    },\n    {\n      \"code\": \"{\\n    \\\"status\\\": \\\"failed\\\",\\n    \\\"errors\\\": {\\n        \\\"orgs_errors\\\": [\\n            {\\n                \\\"error\\\": \\\"Field 'sourcedId' is mandatory but no value was provided.\\\",\\n                \\\"line_number\\\": 3\\n            }\\n        ],\\n        \\\"classes_errors\\\": [\\n            {\\n                \\\"error\\\": \\\"Field 'title' is mandatory but no value was provided.\\\",\\n                \\\"line_number\\\": 1\\n            }\\n        ],\\n        \\\"enrollments_errors\\\": [\\n            {\\n                \\\"error\\\": \\\"Field 'role' is mandatory but no value was provided.\\\",\\n                \\\"line_number\\\": 29\\n            }\\n        ],\\n        \\\"users_errors\\\": [\\n            {\\n                \\\"error\\\": \\\"Field 'username' is mandatory but no value was provided.\\\",\\n                \\\"line_number\\\": 2\\n            }\\n        ]\\n    }\\n}\\n\",\n      \"language\": \"json\",\n      \"name\": \"Failed\"\n    },\n    {\n      \"code\": \"{\\n\\t\\\"status\\\": \\\"accepted\\\",\\n\\t\\\"total_records\\\": {\\n\\t\\t\\\"orgs\\\": 1,\\n\\t\\t\\\"users\\\": 10,\\n\\t\\t\\\"classes\\\": 2,\\n\\t\\t\\\"enrollments\\\": 12\\n\\t},\\n\\t\\\"success_records\\\": {\\n\\t\\t\\\"orgs\\\": 0,\\n\\t\\t\\\"users\\\": 0,\\n\\t\\t\\\"classes\\\": 0,\\n\\t\\t\\\"enrollments\\\": 0\\n\\t}\\n}\\n\",\n      \"language\": \"json\",\n      \"name\": \"Accepted\"\n    },\n    {\n      \"code\": \"{\\n\\t\\\"status\\\": \\\"completed\\\",\\n\\t\\\"total_records\\\": {\\n\\t\\t\\\"orgs\\\": 1,\\n\\t\\t\\\"users\\\": 10,\\n\\t\\t\\\"classes\\\": 2,\\n\\t\\t\\\"enrollments\\\": 12\\n\\t},\\n\\t\\\"success_records\\\": {\\n\\t\\t\\\"orgs\\\": 1,\\n\\t\\t\\\"users\\\": 8,\\n\\t\\t\\\"classes\\\": 2,\\n\\t\\t\\\"enrollments\\\": 10\\n\\t}\\n}\\n\",\n      \"language\": \"json\",\n      \"name\": \"Completed\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"title\": \"Reference\"\n}\n[/block]\n## HTTP Response Codes\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"HTTP Status Code\",\n    \"h-1\": \"HTTP Method\",\n    \"h-2\": \"Response Body\",\n    \"h-3\": \"Description\",\n    \"0-0\": \"200\",\n    \"0-1\": \"GET\",\n    \"0-2\": \"Entity which is requested\",\n    \"0-3\": \"Operation successful without error\",\n    \"1-0\": \"201 Created\",\n    \"1-1\": \"POST\",\n    \"1-2\": \"No Entity in body except for the location of entity in header\",\n    \"1-3\": \"Entity creation successful\",\n    \"2-0\": \"204 No Content\",\n    \"2-1\": \"PUT, DELETE\",\n    \"2-2\": \"No Content\",\n    \"2-3\": \"Entity update or delete is successful\",\n    \"3-0\": \"400 Bad Request\",\n    \"3-1\": \"ALL\",\n    \"3-2\": \"Error messages\",\n    \"3-3\": \"Malformed, invalid or incorrect request or request parameters which are applicable to this Entity\",\n    \"4-0\": \"401 Unauthorized\",\n    \"4-1\": \"ALL\",\n    \"4-2\": \"No Content\",\n    \"4-3\": \"Action requires authentication or session token may have expired. Note that we don’t return www-authenticate headers as we do not want browser to participate in the auth flow.\",\n    \"5-0\": \"403 Forbidden\",\n    \"5-1\": \"ALL\",\n    \"5-2\": \"Error message\",\n    \"5-3\": \"Authentication failure, or invalid API key, or insufficient privileges\",\n    \"6-0\": \"f693bd0a-a67e-4e2d-92c7-0b75d0b0dd3e\",\n    \"6-1\": \"ALL\",\n    \"6-2\": \"No Content\",\n    \"6-3\": \"Entity not found\",\n    \"7-0\": \"405 Not Allowed\",\n    \"7-1\": \"ALL\",\n    \"8-1\": \"ALL\",\n    \"9-1\": \"POST, PUT\",\n    \"7-2\": \"No Content\",\n    \"8-2\": \"No Content\",\n    \"9-2\": \"No Content\",\n    \"10-2\": \"Error message\",\n    \"7-3\": \"Entity does not support the requested operation\",\n    \"8-0\": \"408 Request Timeout\",\n    \"8-3\": \"Request has timed out. The system was not able to complete the operation within specified time\",\n    \"9-0\": \"413 Request Entity Too Large\",\n    \"9-3\": \"The representation of payload is too large for server to handle, or is not allowed\",\n    \"10-0\": \"500 Internal Server Error\",\n    \"10-1\": \"ALL\",\n    \"10-3\": \"Some exception happened while processing the request. The message may be technical and may not be suitable for UI consumption.\"\n  },\n  \"cols\": 4,\n  \"rows\": 11\n}\n[/block]","excerpt":"","slug":"roster-sync-api","type":"basic","title":"Roster Sync API"}
[block:api-header] { "title": "Authentication for APIs" } [/block] All Oneroster APIs are authenticated based on the client id and secret shared by Gooru with partners. Partner need to base64 encode the client id and secret in order to pass as Basic authorization header to APIs. **Example:** (To generate Base64 Encoded Credentials) ClientId: 3d6bc3ea-2aff-4106-8762-9246d5d84813 Secret: kteuobYdO1oRfqJ1+PZ5phMSeI= Combine client id and secret with ‘:’ - 3d6bc3ea-2aff-4106-8762-9246d5d84813:kteuobYdO1oRfqJ1+PZ5phMSeI= And then encode it by Base64 encoder which will generate string like below. Use it to pass in request header. M2Q2YmMzZWEtMmFmZi00MTA2LTg3NjItOTI0NmQ1ZDg0ODEzOmt0ZXVvYllkTzFvUmZxSjErUFo1cGhNU2VJPQ== [block:api-header] { "title": "Upload Roster" } [/block] This API is used to upload the roster files in zip format. All csv files contained in the zip should comply to the [IMS Global Oneroster specification](https://www.imsglobal.org/lis/imsOneRosterv1p0/imsOneRosterCSV-v1p0.html). Invalid or extra uploaded files are skipped from rostering. Current scope of this API is to process orgs, users, classes and enrollments only. Other files such as academicSessions, demographics and courses will be not be processed and rostered into system. All data will be rostered against the client id (tenant) in Gooru. Client applications need to provide same client id and secret while performing SSO which id used while rostering the users. This API will not return any details on error / exceptions for the failed records. Status API should be explicitly called with required parameters to get the status / error while rostering files. [block:parameters] { "data": { "h-0": "Name", "h-1": "Value", "0-0": "HTTP Method", "0-1": "POST", "1-0": "End Point", "1-1": "http://{host}/api/nucleus-oneroster/{version}/upload", "2-0": "Sample", "2-1": "http://oneroster.gooru.org/api/nucleus-oneroster/v1/upload" }, "cols": 2, "rows": 3 } [/block] ###Headers [block:parameters] { "data": { "h-0": "Header Name", "h-1": "Value", "0-0": "Authorization", "0-1": "Basic <BASE64 ENCODED CREDENTIALS>", "1-0": "Content-Type", "1-1": "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW" }, "cols": 2, "rows": 2 } [/block] * Replace the correct value of encoded credentials in ‘Authorization’ header * Boundary in the ‘Content-Type’ header is sample. Need to be replaced with actual boundary while calling the API. ###Request Payload Attach the file with request. ###Success Reponse HTTP Status Code: 201 Created Location header of the response will contain the Upload Id which can be used to get the status of the upload. ###Error Response In case of any error while uploading the Roster, API will not provide any details of error / exceptions for records in the files. For Error response codes, refer to Reference section in this document. [block:api-header] { "title": "Get Upload Status" } [/block] This API is used to get the status of the upload for give upload id. For now this API will return total records and success record counts. It may be enhanced in future to return records level details. [block:parameters] { "data": { "h-0": "Name", "h-1": "Value", "0-0": "HTTP Method", "0-1": "GET", "1-0": "End Point", "1-1": "http://{host}/api/nucleus-oneroster/{version}/upload/{uploadId}/status", "2-0": "Sample", "2-1": "http://oneroster.gooru.org/api/nucleus-oneroster/v1/upload/62f3fbd3-4341-4e30-8efe-3b655074133d/status" }, "cols": 2, "rows": 3 } [/block] ###Headers [block:parameters] { "data": { "h-0": "Header Name", "h-1": "Value", "0-0": "Authorization", "0-1": "Basic <BASE64 ENCODED CREDENTIALS>" }, "cols": 2, "rows": 1 } [/block] * Replace the correct value of encoded credentials in ‘Authorization’ header. ###Request Payload No request payload required for this API ###Success Response HTTP Status Code: 200 OK ###Error Response Refer to reference section of this document below. ###Possible Status [block:parameters] { "data": { "h-0": "Status", "h-1": "Purpose", "0-0": "pending", "0-1": "Denotes the zip upload is success and pending to be process. The uploads are queued at server and picked up one by one.", "1-0": "accepted", "1-1": "Denotes that the upload zip file has been accepted for rostering. This is the status after parsing and validation of all csv files, and still the sync with Gooru main database is pending.", "2-0": "failed", "2-1": "Denotes that the upload has been failed. In case of failure while rostering records, this status will be returned.", "3-0": "completed", "3-1": "Denotes that the upload has been complete. When all records are rostered successfully, this status will be returned." }, "cols": 2, "rows": 4 } [/block] ##Responses [block:code] { "codes": [ { "code": "{\n\t\"status\": \"pending\",\n\t\"total_records\": {\n\t\t\"orgs\": 1,\n\t\t\"users\": 10,\n\t\t\"classes\": 2,\n\t\t\"enrollments\": 12\n\t},\n\t\"success_records\": {\n\t\t\"orgs\": 1,\n\t\t\"users\": 8,\n\t\t\"classes\": 2,\n\t\t\"enrollments\": 10\n\t}\n}\n", "language": "json", "name": "Pending" }, { "code": "{\n \"status\": \"failed\",\n \"errors\": {\n \"orgs_errors\": [\n {\n \"error\": \"Field 'sourcedId' is mandatory but no value was provided.\",\n \"line_number\": 3\n }\n ],\n \"classes_errors\": [\n {\n \"error\": \"Field 'title' is mandatory but no value was provided.\",\n \"line_number\": 1\n }\n ],\n \"enrollments_errors\": [\n {\n \"error\": \"Field 'role' is mandatory but no value was provided.\",\n \"line_number\": 29\n }\n ],\n \"users_errors\": [\n {\n \"error\": \"Field 'username' is mandatory but no value was provided.\",\n \"line_number\": 2\n }\n ]\n }\n}\n", "language": "json", "name": "Failed" }, { "code": "{\n\t\"status\": \"accepted\",\n\t\"total_records\": {\n\t\t\"orgs\": 1,\n\t\t\"users\": 10,\n\t\t\"classes\": 2,\n\t\t\"enrollments\": 12\n\t},\n\t\"success_records\": {\n\t\t\"orgs\": 0,\n\t\t\"users\": 0,\n\t\t\"classes\": 0,\n\t\t\"enrollments\": 0\n\t}\n}\n", "language": "json", "name": "Accepted" }, { "code": "{\n\t\"status\": \"completed\",\n\t\"total_records\": {\n\t\t\"orgs\": 1,\n\t\t\"users\": 10,\n\t\t\"classes\": 2,\n\t\t\"enrollments\": 12\n\t},\n\t\"success_records\": {\n\t\t\"orgs\": 1,\n\t\t\"users\": 8,\n\t\t\"classes\": 2,\n\t\t\"enrollments\": 10\n\t}\n}\n", "language": "json", "name": "Completed" } ] } [/block] [block:api-header] { "title": "Reference" } [/block] ## HTTP Response Codes [block:parameters] { "data": { "h-0": "HTTP Status Code", "h-1": "HTTP Method", "h-2": "Response Body", "h-3": "Description", "0-0": "200", "0-1": "GET", "0-2": "Entity which is requested", "0-3": "Operation successful without error", "1-0": "201 Created", "1-1": "POST", "1-2": "No Entity in body except for the location of entity in header", "1-3": "Entity creation successful", "2-0": "204 No Content", "2-1": "PUT, DELETE", "2-2": "No Content", "2-3": "Entity update or delete is successful", "3-0": "400 Bad Request", "3-1": "ALL", "3-2": "Error messages", "3-3": "Malformed, invalid or incorrect request or request parameters which are applicable to this Entity", "4-0": "401 Unauthorized", "4-1": "ALL", "4-2": "No Content", "4-3": "Action requires authentication or session token may have expired. Note that we don’t return www-authenticate headers as we do not want browser to participate in the auth flow.", "5-0": "403 Forbidden", "5-1": "ALL", "5-2": "Error message", "5-3": "Authentication failure, or invalid API key, or insufficient privileges", "6-0": "f693bd0a-a67e-4e2d-92c7-0b75d0b0dd3e", "6-1": "ALL", "6-2": "No Content", "6-3": "Entity not found", "7-0": "405 Not Allowed", "7-1": "ALL", "8-1": "ALL", "9-1": "POST, PUT", "7-2": "No Content", "8-2": "No Content", "9-2": "No Content", "10-2": "Error message", "7-3": "Entity does not support the requested operation", "8-0": "408 Request Timeout", "8-3": "Request has timed out. The system was not able to complete the operation within specified time", "9-0": "413 Request Entity Too Large", "9-3": "The representation of payload is too large for server to handle, or is not allowed", "10-0": "500 Internal Server Error", "10-1": "ALL", "10-3": "Some exception happened while processing the request. The message may be technical and may not be suitable for UI consumption." }, "cols": 4, "rows": 11 } [/block]