Skip to content

Apply ​

Call scholarships.applyV2 once to create the application. Call scholarships.submitApplicationRequirementV2 once for each answer. When Owlflow returns viewer.allMandatoryRequirementsCompleted: true, the student has finished the application. Don't make another submission call.

Include Authorization: Bearer <token> on each request. Before rendering the application form, load the requirement IDs, validation rules, and limits from the scholarship detail query.

Both V2 mutations return the updated scholarship and application progress. Don't reload scholarships.byId after every saved answer.

Open the application ​

graphql
mutation Apply($scholarshipId: ID!, $subSource: String) {
  scholarships {
    applyV2(scholarshipId: $scholarshipId, subSource: $subSource) {
      application { id dateApplied }
      scholarship {
        id
        title
        viewer { hasApplication hasSubmitted allMandatoryRequirementsCompleted }
      }
    }
  }
}
json
{ "scholarshipId": "12345", "subSource": "partner-site" }

Use subSource to record where the student began the application, such as a page or campaign on your site. A successful applyV2 call sets viewer.hasApplication to true. If the scholarship has no mandatory requirements, Owlflow may also mark the application complete immediately.

Save one answer ​

Set requirementId to the requirement definition's ID and scholarshipId to the scholarship ID. Include id only when replacing a saved response that already has an applicationRequirement.id.

graphql
mutation SaveRequirement($input: ApplicationRequirementInput!) {
  scholarships {
    submitApplicationRequirementV2(input: $input) {
      applicationRequirement { id }
      scholarship {
        id
        viewer {
          allMandatoryRequirementsCompleted
          requirementProgress { completed progress }
        }
      }
    }
  }
}

Store the applicationRequirement.id that Owlflow returns. You'll need it to replace or delete the response later.

Core writes a GOAL response once. Repeating the mutation doesn't update the stored payload.

Short answer (INPUT) ​

json
{
  "input": {
    "type": "INPUT",
    "scholarshipId": "12345",
    "requirementId": "901",
    "text": "Lincoln High School"
  }
}

Display title and description as the prompt. Apply any validation rules from config.

Essay (TEXT) ​

json
{
  "input": {
    "type": "TEXT",
    "scholarshipId": "12345",
    "requirementId": "902",
    "text": "I want to study computer science because..."
  }
}

Validate the response against minWords, maxWords, minCharacters, and maxCharacters. If the requirement includes essayTopics, show those prompts before the student writes.

When allowFile is true, the student may upload a document instead of entering text. Send the document in fileBase64 with its fileName, and validate it against allowedExtensions and maxFileSize in bytes. The optional source field can identify where the student found the scholarship, such as search or recommended.

AI drafts are optional. See Essays.

Survey (SURVEY) ​

The answers object maps each question id to an array of selected option values. Radio questions contain one value, while checkbox questions may contain several. Send questions.options.value, not the display label.

json
{
  "input": {
    "type": "SURVEY",
    "scholarshipId": "12345",
    "requirementId": "903",
    "answers": {
      "q-1": ["yes"],
      "q-2": ["leadership", "community"]
    }
  }
}

Confirmation (SPECIAL_ELIGIBILITY) ​

Display the requirement's specialEligibilityValue as the confirmation statement. When the student checks the box, save the string true as the response.

json
{
  "input": {
    "type": "SPECIAL_ELIGIBILITY",
    "scholarshipId": "12345",
    "requirementId": "904",
    "specialEligibilityValue": "true"
  }
}

File (FILE) and image (IMAGE) ​

json
{
  "input": {
    "type": "FILE",
    "scholarshipId": "12345",
    "requirementId": "905",
    "fileName": "transcript.pdf",
    "fileBase64": "<base64>"
  }
}

For an image, use type: "IMAGE" and validate the file against allowedFormats rather than allowedExtensions. When the requirement provides dimensions, also enforce minWidth, maxWidth, minHeight, and maxHeight. To attach a file the student has already uploaded, send accountFileId instead of fileBase64.

Goal (GOAL) ​

Direct the student to link. The variant is either TRACKING_MODE_FULL or TRACKING_MODE_LINK. After the student completes the goal, save a JSON object such as:

json
{
  "input": {
    "type": "GOAL",
    "scholarshipId": "12345",
    "requirementId": "906",
    "goalValue": { "source": "partner-site", "completedAt": "2026-10-06T18:00:00.000Z" }
  }
}

Replace or remove an answer ​

To replace a response, call submitApplicationRequirementV2 with id set to the existing applicationRequirement.id.

Call deleteApplicationRequirementV2 to remove an answer:

graphql
mutation DeleteRequirement($id: ID!, $scholarshipId: ID!, $type: RequirementTypeEnum!) {
  scholarships {
    deleteApplicationRequirementV2(id: $id, scholarshipId: $scholarshipId, type: $type) {
      scholarship {
        id
        viewer { allMandatoryRequirementsCompleted }
      }
    }
  }
}
json
{ "id": "555", "scholarshipId": "12345", "type": "TEXT" }

Here, id refers to the saved response rather than the requirement definition.

You don't need to save a response for an optional requirement. When isOptional is true, the student can complete the application without it.

Owlflow partner API