File Upload

Instructions

File uploading involves two phases: uploading a file, and processing the uploaded file.

Uploading a File

Uploading a file is a two step process of getting policy info and then uploading the actual file.

Getting Policy Info

  • In the body of the request, content_type should be the MIME type for the file you will be uploading, e.g. application/zip, text/csv
  • In most cases you will set multipart to false. This document does not cover multipart upload
  • You need to use your own API token in the Authorization header
curl https://example.bridgeapp.com/api/author/file_upload_policies\
 -H 'Content-Type: application/json'\
 -H 'Authorization: Basic NjViY2YyNWUtNWQ4NS00N2E2LTgyZWItZTRmRhZWQ3NA=='\
 -d '{"content_type": "application/zip", "multipart": false, "aws_sig_v": "4"}' > policy.json
When you request the policy info, the response should look like:
 {
   "policies": [
     {
       "bucket": "abc.instructure",
       "s3_url": "https://s3.amazonaws.com",
       "bucket_url": "https://abc.instructure.s3.amazonaws.com",
       "region": "us-east-2",
       "conditions": {
         "policy": "eyJleHBpcmF0aW9uIjoiMjAxNi0wNC0yOFQxNzoyNDoxOFoiLCJ5zIjpbeyJhyJis=",
         "acl": "private",
         "key": "uploads/45718ec0-a3f6-46a2-9536-805aeebd5.zip",
         "Content-Type": "application/zip",
         "x-amz-signature": "1b8fe950a0b414311762546c05661f6f0e3421bd2733c1fc0cacb06cdf0af8ef",
         "x-amz-credential":"AKIAJD6TVVUTBXGA7LKQ/20200424/us-east-2/s3/aws4_request",
         "x-amz-algorithm":"AWS4-HMAC-SHA256",
         "x-amz-date":"20200424T161359Z",
         "success_action_status": "201"
       }
     }
   ]
 }

Uploading The File

Once you have the policy info, you can upload your file. The upload request is dependent on specific information from the policy response. (Do not change the order of arguments.)

curl -k -i $(jq -r '.policies[0].bucket_url' < policy.json)\
 -F "key=$(jq -r '.policies[0].conditions.key' < policy.json)"\
 -F "acl=$(jq -r '.policies[0].conditions.acl' < policy.json)"\
 -F "policy=$(jq -r '.policies[0].conditions.policy' < policy.json)"\
 -F "x-amz-signature=$(jq -r '.policies[0].conditions["x-amz-signature"]' < policy.json)"\
 -F "x-amz-credential=$(jq -r '.policies[0].conditions["x-amz-credential"]' < policy.json)"\
 -F "x-amz-algorithm=$(jq -r '.policies[0].conditions["x-amz-algorithm"]' < policy.json)"\
 -F "x-amz-date=$(jq -r '.policies[0].conditions["x-amz-date"]' < policy.json)"\
 -F "Content-Type=$(jq -r '.policies[0].conditions["Content-Type"]' < policy.json)"\
 -F "success_action_status=$(jq -r '.policies[0].conditions.success_action_status' < policy.json)"\
 -F file=@filename.zip | grep Location: | sed -e 's/Location: //'\
 | sed -e 's/\%2F/\//' | tr -d '\r\n' > location.txt

When you upload the file, the contents of location.txt should look like:

https://abc.instructure.s3.amazonaws.com/uploads/45718ec0-a3f6-46a2-9536-805aeebd5.zip

Next we’ll describe two of the major use cases: uploading and processing CSV files, and uploading and processing SCORM packages.

Processing an Uploaded CSV File

After uploading, there are 3 more steps to process the file: defining CSV headers for your import and starting preprocessing, checking its preprocessing status, and confirming the upload is complete. Those steps are dependent upon the response from the initial upload request described above.

Define Headers for the CSV File and Start Preprocessing

curl https://example.bridgeapp.com/api/admin/users/import\
 -H 'Content-Type: application/json'\
 -H 'Authorization: Basic NjViY2YyNWUtNWQ4NS00N2E2LTgyZWItZTRmRhZWQ3NA=='\
 -d '{ "context_type": "User", "file": { "fields": {"0": ["uid", "email"],
 "1": "first_name", "2": "last_name", "3": "password", "4": "2",
 "5": ["manager_uid"] }, "has_headers": false,
 "url": '"\"$(cat location.txt)\" } }" > import.json

Header Details

The body of this POST sets the import context and provides details about the file.

The context_type field describes the context in which the import will run. This document only describes the User context.

The has_headers field describes whether the CSV has a header row. If this value is false, all rows will be processed. If true, the first row will be skipped.

The url field describes the location of the file to import.

The fields field describes a mapping from CSV columns to Bridge fields. The key of each mapping is the 0-based index of the CSV column, and the value may be one of three types: the stringified id of a custom field; the standard Bridge user fields ("first_name", "last_name", "sortable_name", "hris_id", "locale", "full_name", "email", "password"); or an array containing one of "uid" or "manager_uid", plus one more field to which the column should also be mapped. Each key or value may be used only once, and, at a minimum, there must be a mapping to ["uid"].

 {
   "context_type": "User",
   "has_headers": false,
   "url": "https://example.s3.amazonaws.com/imports%2F2%2F704758-5e8b-4ad7-b5c6-eb9aa5.csv",
   "file": {
     "fields": {
       "0": ["uid", "email"],
       "1": "first_name",
       "2": "last_name",
       "3": "password",
       "4": "2",
       "5": ["manager_uid"]
     }
   }
 }
The contents of import.json should look like:
 {"linked":
   {
     "contexts":[
       {
         "id":1,
         "class":"Domain"
       }
     ]
   },
   "imports":
   [
     {
       "id":"10",
       "context_id":"1",
       "context_type":"Domain",
       "completed":0,
       "total":0,
       "state":"incomplete",
       "new_user_count":0,
       "restored_user_count":0,
       "updated_user_count":0,
       "deleted_user_count":0,
       "ignored_user_count":0,
       "deported_user_count":0,
       "invalid_rows":[],
       "created_at":"2016-05-12T15:47:10.379-06:00"
     }
   ]
 }

Check Status

curl "https://example.bridgeapp.com/api/admin/users/imports/$(jq -r '.imports[0].id' < import.json)"\
 -H 'Content-Type: application/json'\
 -H 'Authorization: Basic NjViY2YyNWUtNWQ4NS00N2E2LTgyZWItZTRmRhZWQ3NA=='\
 | jq '.imports[0].state'
The result should look like:
%     Total    %  Received %   Xferd  Average   Speed    Time    Time     Time   Current
                                       Dload    Upload   Total   Spent    Left    Speed
100   358     100   358    0     0     1223     0     --:--:-- --:--:-- --:--:--  1230
"complete"

Confirmation

Once you get the status complete, you must confirm the import for final processing.

curl "https://example.bridgeapp.com/api/admin/users/imports/$(jq -r '.imports[0].id' < import.json)/confirm"\
 -X POST -H 'Content-Type: application/json'\
 -H 'Authorization: Basic NjViY2YyNWUtNWQ4NS00N2E2LTgyZWItZTRmRhZWQ3NA==' -d ''

Processing a SCORM Package

Once you have uploaded the file, there are a few ways to finish importing the SCORM package.

Example A

First use the SCORM upload endpoint to create a new course. This is completed asynchronously, so you must check afterward to see if the upload and create is complete.

curl https://example.bridgeapp.com/api/scorm/upload\
 -H 'Authorization: Basic NjViY2YyNWUtNWQ4NS00N2E2LTgyZWItZTRmRhZWQ3NA=='\
 -H 'Content-Type: application/json'\
 -H 'Accept: application/json'\
 -d '{ "title": "Concept Evaluation: Identifying Opportunities",
 "url": '"\"$(cat location.txt)\" }"\
 | jq -r '.id' > id.txt

Check for completion:

curl "https://example.bridgeapp.com/api/author/course_templates/$(cat id.txt)"\
 -H 'Authorization: Basic NjViY2YyNWUtNWQ4NS00N2E2LTgyZWItZTRmRhZWQ3NA=='\
 -H 'Content-Type: application/json'\
 -H 'Accept: application/json' | jq -r '.course_templates[0].external_status'

When you get a completed response, the course is ready to publish.

curl "https://example.bridgeapp.com/api/author/course_templates/$(cat id.txt)/publish"\
 -H 'Authorization: Basic NjViY2YyNWUtNWQ4NS00N2E2LTgyZWItZTRmRhZWQ3NA=='\
 -H 'Content-Type: application/json' -d ''

Example B

This method will result in the SCORM package appearing as an attachment to the Bridge course. By default, the attachment is only visible to authors.

First create a course. This may be done via the api/scorm/upload endpoint as in Example A, or you can create a blank course through the normal course creation endpoint. This endpoint requires an author, so pass your user id in the query parameter as_user_id.

curl https://example.bridgeapp.com/api/author/course_templates?as_user_id=4324\
 -H 'Authorization: Basic NjViY2YyNWUtNWQ4NS00N2E2LTgyZWItZTRmRhZWQ3NA=='\
 -H 'Content-Type: application/json'\
 -H 'Accept: application/json'\
 -d '{"course_templates": [{}]}' | jq -r '.course_templates[0].id' > id.txt

Then send the SCORM file to Bridge as an attachment to the course. The name parameter is the filename you would like Bridge to display. This endpoint expects location not to be URL-encoded.

curl -i "https://example.bridgeapp.com/api/author/course_templates/$(cat id.txt)/attach_scorm"\
 -H 'Authorization: Basic NjViY2YyNWUtNWQ4NS00N2E2LTgyZWItZTRmRhZWQ3NA=='\
 -H 'Content-Type: application/json'\
 -d '{ "name": "001-01-concept-evaluation-identifying-opportunities.zip",
 "location": '"\"$(cat location.txt)\" }"

After attaching, notify Bridge to import the attachment as a SCORM course. The title and description will be automatically populated if they are currently blank. This endpoint also automatically publishes the course if the import is successful. The import is processed asynchronously.

curl "https://example.bridgeapp.com/api/author/course_templates/$(cat id.txt)/import_attached_scorm"\
 -H 'Authorization: Basic NjViY2YyNWUtNWQ4NS00N2E2LTgyZWItZTRmRhZWQ3NA=='\
 -H 'Content-Type: application/json' -d ''