Skip to content
Woolf Help Center home
Woolf Help Center home

Bulk upload of student activities

This guide explains how to bulk upload student activities (grades, feedback, submissions, and content consumption) using the bulk upload API.

Overview

The bulk upload flow is asynchronous and file-based:

  1. Request an upload session

  2. Receive a jobId and uploadUrl

  3. Upload an NDJSON file with activity records

  4. Track results using the jobId via API or webhook

Step 1: Request upload session

Call the bulkUploadActivity API.

Request

No input required.

Response

//request { "query": "mutation { bulkUploadActivity}" } //response { "data": { "bulkUploadActivity": { "jobId": "bf9003b3-a943-475f-92ff-7c44dd344282", "uploadUrl": "https://storage.googleapis.com/woolf-local-filestore/bulk-upload/bf9003b3-a943-475f-92ff-7c44dd344282/bulk-activity-import-d30354b1-1f0f-4845-b8a9-8bfe57966ec4-2025-10-13T07-09-27-715Z.ndjson?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=stackdriver-exporter%40graphic-fiber-237613.iam.gserviceaccount.com%2F20251013%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20251013T070939Z&X-Goog-Expires=7200&X-Goog-SignedHeaders=content-disposition%3Bcontent-type%3Bhost%3Bx-goog-meta-name%3Bx-goog-meta-type&X-Goog-Signature=9e50b8597a1c4aeb83ebfcbf24b465f25f9c8ef65f0db24679b1937a6718d6ef9edca36460186eec982184b1017bec4c6aeda6b3e308acacca92a5918e872f5fd326ce8b5621fa0a6c71f429ac32305c99dfc7373eb179adf7b9f7e664f71ac0688caa6b97be191765eec917e272b2d7f759c7428f1c8ea6756f6113e96374fd5bfbd327e76db29f69d5b192b52b62da87f8adb7fcca2a2c3144b8a850aabe6c2759d380097c094f908e4f4ed4f124bdb91079f6362914146480ba02f6ae40fb52d82fa1d32775f4d67a0a9f7951bb587ac75ddc5e3aec1c36f61d9b3425352743f6e23263a6383ac5bd9d25a1cb5b83648a56a23bf259aa3284dbc88e7c5522", "headers": { "Content-Disposition": "inline; filename=\"bulk-activity-import-d30354b1-1f0f-4845-b8a9-8bfe57966ec4-2025-10-13T07-09-27-715Z.ndjson\"", "x-goog-meta-name": "bulk-activity-import-d30354b1-1f0f-4845-b8a9-8bfe57966ec4-2025-10-13T07-09-27-715Z.ndjson", "Content-Type": "application/x-ndjson", "x-goog-meta-type": "application/x-ndjson" } } } }

What to do next

  • Store the jobId on your side — this is required to track results via API or webhook

  • Use the uploadUrl to upload your file

Step 2: Prepare your NDJSON file

File requirements

  • Format: NDJSON (Newline Delimited JSON)

  • Max file size: 20 MB

  • Each line = one activity record

  • No enclosing array — each JSON object must be on a separate line

NDJSON structure

Each line must follow this structure:

{ "mutationType": "Grade" | "Feedback" | "Submission" | "Consumption", "payload": { ... } }

Unified payload schema

// ndjson row input schema { mutationType: "Grade" | "Feedback" | "Submission" | "Consumption", payload: AddGradeInput | AddFeedBackInput | AddSubmissionInput | AddConsumptionInput } // AddGradeInput { resourceId: String studentId: String! teacherId: String weightId: ID value: Float! assets: [{ importUrl: String }] // url to asset that Woolf can upload evidenceAssets: [{ importUrl: String }] // url to asset that Woolf can upload } // AddFeedBackInput { resourceId: String studentId: String! teacherId: String content: String assets: [{ importUrl: String }] evidenceAssets: [{ importUrl: String }] } // AddSubmissionInput { resourceId: String studentId: String! content: String assets: [{ importUrl: String }] evidenceAssets: [{ importUrl: String }] } // AddConsumptionInput { studentId: String resourceId: String createdAt: Date evidenceAssets: [{ importUrl: String }] assets: [{ importUrl: String }] }

Step 3: Upload file

Upload to uploadUrl.

Step 4: Results

  • Processing is asynchronous

  • Use jobId to track the upload

You can get results in two ways:

  • query the job status using API jobDetails(jobId: String!)

  • subscribe to webhook events and receive notifications automatically

The jobId returned by bulkUploadActivity must be stored on your side. It is the identifier used to check the upload result later.

Query upload results

Use the jobDetails API to check the status and result of a bulk upload job.

API

jobDetails(jobId: String!): JobDetails!

Receive results by webhook

If you do not want to repeatedly call the query API, you can subscribe to webhook events and receive notifications when the job finishes processing.

Learn how to manage webhooks here.

Recommended flow for bulk upload results:

  1. Call bulkUploadActivity

  2. Store the returned jobId

  3. Upload the NDJSON file to uploadUrl

  4. Subscribe to webhook notifications if you want automatic updates

  5. Optionally call jobDetails(jobId) to check progress or confirm final results