Resolve an imported attendance recipient
Requires participation_configure, programs_view and access to this organization’s program, with participation enabled. Only batches in review can be changed. Match selects one of the reviewed candidate IDs and must respect current placement; provisional marks a new recipient for creation at commit, unresolved preserves unresolved evidence, and skip excludes it. Applies the decision to all ready/review/unresolved observations sharing the same source-record fingerprint, then refreshes batch counts. Blocked rows require mapping correction and revalidation. Requires permission: one of participation_configure.
curl --request PATCH \
--url https://api.gratona.com/v1/admin/programs/{program_id}/participation/imports/{participation_import_id}/rows/{participation_import_row_id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"decision": "match",
"entity_id": 42
}
'import requests
url = "https://api.gratona.com/v1/admin/programs/{program_id}/participation/imports/{participation_import_id}/rows/{participation_import_row_id}"
payload = {
"decision": "match",
"entity_id": 42
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({decision: 'match', entity_id: 42})
};
fetch('https://api.gratona.com/v1/admin/programs/{program_id}/participation/imports/{participation_import_id}/rows/{participation_import_row_id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.gratona.com/v1/admin/programs/{program_id}/participation/imports/{participation_import_id}/rows/{participation_import_row_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'decision' => 'match',
'entity_id' => 42
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.gratona.com/v1/admin/programs/{program_id}/participation/imports/{participation_import_id}/rows/{participation_import_row_id}"
payload := strings.NewReader("{\n \"decision\": \"match\",\n \"entity_id\": 42\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.gratona.com/v1/admin/programs/{program_id}/participation/imports/{participation_import_id}/rows/{participation_import_row_id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"decision\": \"match\",\n \"entity_id\": 42\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gratona.com/v1/admin/programs/{program_id}/participation/imports/{participation_import_id}/rows/{participation_import_row_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"decision\": \"match\",\n \"entity_id\": 42\n}"
response = http.request(request)
puts response.read_body{
"row": {
"id": 84,
"sheet": "Sheet1",
"source_row_number": 2,
"attendance_date": "2026-10-20",
"display_name": "Jane Recipient",
"gratona_id": "42",
"external_student_id": "STU-001",
"site_id": 12,
"cohort_id": 18,
"site_source_value": "Main campus",
"cohort_source_value": "Group A",
"symbol": "P",
"encounter_status": "seen",
"enrollment_confirmation": "confirmed_enrolled",
"match_type": "suggested_candidate",
"decision": "match",
"status": "review",
"entity_id": 42,
"candidates": [
{
"entity_id": 42,
"gratona_id": 42,
"display_name": "Jane Recipient",
"site_id": 12,
"cohort_id": 18,
"score": 95,
"agreed": [
"name"
],
"conflicted": [
"gender"
]
}
],
"errors": [
"placement_conflict"
],
"warnings": [
"candidate_confirmation_required"
],
"participation_session_id": 120
},
"batch": {
"id": 42,
"program_id": 12,
"participation_period_id": 18,
"original_filename": "attendance.xlsx",
"source_type": "xlsx",
"status": "review",
"progress": 100,
"mapping": {
"evidence_source": "official_record",
"existing_session_action": "block",
"symbols": {},
"sheets": [
{
"sheet": "Sheet1",
"header_row": 1,
"columns": {
"name": 0,
"gratona_id": 0,
"student_id": 0,
"gender": 0
},
"site": {
"fixed_id": 42,
"column": 0,
"value_map": {}
},
"cohort": {
"fixed_id": 42,
"column": 0,
"value_map": {}
},
"attendance_columns": [
{
"column": 4,
"date": "2026-10-20"
}
],
"enabled": true,
"profile_columns": {}
}
],
"external_student_id_field_key": "student_id",
"gender_field_key": "gender"
},
"inspection": [
{
"name": "Sheet1",
"suggested_header_row": 1,
"columns": [
{
"index": 0,
"letter": "A"
}
],
"sample_rows": [
{
"row_number": 2,
"values": [
"Jane Recipient"
]
}
]
}
],
"summary": {
"total_rows": 1,
"ready_rows": 1,
"review_rows": 1,
"blocked_rows": 1,
"unresolved_rows": 1,
"committed_rows": 1,
"skipped_rows": 1,
"exact_id_matches": 1,
"provisional_rows": 1,
"estimated_rows": 1,
"maximum_rows": 1
},
"validation_errors": [
{
"sheet": "Sheet1",
"row": 2,
"date": "2026-10-20",
"codes": [
"placement_conflict"
]
}
],
"error_message": "The attendance file could not be validated. Review the mapping and retry.",
"failure_stage": "validation",
"can_commit": true,
"can_void": false,
"created_at": "2026-10-20T12:00:00Z",
"completed_at": "2026-10-20T12:05:00Z",
"voided_at": "2023-11-07T05:31:56Z",
"void_reason": "Imported the incorrect workbook.",
"created_checks": [
{
"id": 120,
"scheduled_for": "2026-10-20",
"status": "submitted",
"revision": 1,
"site": {
"id": 12,
"name": "Main campus"
},
"cohort": {
"id": 12,
"name": "Main campus"
},
"counts": {
"expected": 25,
"seen": 23,
"unresolved": 2
}
}
],
"rows": {
"items": [
{
"id": 84,
"sheet": "Sheet1",
"source_row_number": 2,
"attendance_date": "2026-10-20",
"display_name": "Jane Recipient",
"gratona_id": "42",
"external_student_id": "STU-001",
"site_id": 12,
"cohort_id": 18,
"site_source_value": "Main campus",
"cohort_source_value": "Group A",
"symbol": "P",
"encounter_status": "seen",
"enrollment_confirmation": "confirmed_enrolled",
"match_type": "suggested_candidate",
"decision": "match",
"status": "review",
"entity_id": 42,
"candidates": [
{
"entity_id": 42,
"gratona_id": 42,
"display_name": "Jane Recipient",
"site_id": 12,
"cohort_id": 18,
"score": 95,
"agreed": [
"name"
],
"conflicted": [
"gender"
]
}
],
"errors": [
"placement_conflict"
],
"warnings": [
"candidate_confirmation_required"
],
"participation_session_id": 120
}
],
"total": 25,
"current_page": 1,
"per_page": 50,
"last_page": 1
},
"recipient_fields": [
{
"key": "student_id",
"label": "Student ID",
"type": "hysCustomID",
"is_title": false
}
]
}
}{
"message": "Unauthorized",
"status": "error"
}{
"message": "Not Found",
"status": "error"
}{
"errors": {},
"status": "error",
"message": "The given data was invalid."
}Authorizations
Passport bearer token authentication for legacy admin sessions.
Path Parameters
Program id in the current organization.
Participation import id in the current organization.
Participation import row id in the current organization.
Body
Validated request fields for this operation.
curl --request PATCH \
--url https://api.gratona.com/v1/admin/programs/{program_id}/participation/imports/{participation_import_id}/rows/{participation_import_row_id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"decision": "match",
"entity_id": 42
}
'import requests
url = "https://api.gratona.com/v1/admin/programs/{program_id}/participation/imports/{participation_import_id}/rows/{participation_import_row_id}"
payload = {
"decision": "match",
"entity_id": 42
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({decision: 'match', entity_id: 42})
};
fetch('https://api.gratona.com/v1/admin/programs/{program_id}/participation/imports/{participation_import_id}/rows/{participation_import_row_id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.gratona.com/v1/admin/programs/{program_id}/participation/imports/{participation_import_id}/rows/{participation_import_row_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'decision' => 'match',
'entity_id' => 42
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.gratona.com/v1/admin/programs/{program_id}/participation/imports/{participation_import_id}/rows/{participation_import_row_id}"
payload := strings.NewReader("{\n \"decision\": \"match\",\n \"entity_id\": 42\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.gratona.com/v1/admin/programs/{program_id}/participation/imports/{participation_import_id}/rows/{participation_import_row_id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"decision\": \"match\",\n \"entity_id\": 42\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gratona.com/v1/admin/programs/{program_id}/participation/imports/{participation_import_id}/rows/{participation_import_row_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"decision\": \"match\",\n \"entity_id\": 42\n}"
response = http.request(request)
puts response.read_body{
"row": {
"id": 84,
"sheet": "Sheet1",
"source_row_number": 2,
"attendance_date": "2026-10-20",
"display_name": "Jane Recipient",
"gratona_id": "42",
"external_student_id": "STU-001",
"site_id": 12,
"cohort_id": 18,
"site_source_value": "Main campus",
"cohort_source_value": "Group A",
"symbol": "P",
"encounter_status": "seen",
"enrollment_confirmation": "confirmed_enrolled",
"match_type": "suggested_candidate",
"decision": "match",
"status": "review",
"entity_id": 42,
"candidates": [
{
"entity_id": 42,
"gratona_id": 42,
"display_name": "Jane Recipient",
"site_id": 12,
"cohort_id": 18,
"score": 95,
"agreed": [
"name"
],
"conflicted": [
"gender"
]
}
],
"errors": [
"placement_conflict"
],
"warnings": [
"candidate_confirmation_required"
],
"participation_session_id": 120
},
"batch": {
"id": 42,
"program_id": 12,
"participation_period_id": 18,
"original_filename": "attendance.xlsx",
"source_type": "xlsx",
"status": "review",
"progress": 100,
"mapping": {
"evidence_source": "official_record",
"existing_session_action": "block",
"symbols": {},
"sheets": [
{
"sheet": "Sheet1",
"header_row": 1,
"columns": {
"name": 0,
"gratona_id": 0,
"student_id": 0,
"gender": 0
},
"site": {
"fixed_id": 42,
"column": 0,
"value_map": {}
},
"cohort": {
"fixed_id": 42,
"column": 0,
"value_map": {}
},
"attendance_columns": [
{
"column": 4,
"date": "2026-10-20"
}
],
"enabled": true,
"profile_columns": {}
}
],
"external_student_id_field_key": "student_id",
"gender_field_key": "gender"
},
"inspection": [
{
"name": "Sheet1",
"suggested_header_row": 1,
"columns": [
{
"index": 0,
"letter": "A"
}
],
"sample_rows": [
{
"row_number": 2,
"values": [
"Jane Recipient"
]
}
]
}
],
"summary": {
"total_rows": 1,
"ready_rows": 1,
"review_rows": 1,
"blocked_rows": 1,
"unresolved_rows": 1,
"committed_rows": 1,
"skipped_rows": 1,
"exact_id_matches": 1,
"provisional_rows": 1,
"estimated_rows": 1,
"maximum_rows": 1
},
"validation_errors": [
{
"sheet": "Sheet1",
"row": 2,
"date": "2026-10-20",
"codes": [
"placement_conflict"
]
}
],
"error_message": "The attendance file could not be validated. Review the mapping and retry.",
"failure_stage": "validation",
"can_commit": true,
"can_void": false,
"created_at": "2026-10-20T12:00:00Z",
"completed_at": "2026-10-20T12:05:00Z",
"voided_at": "2023-11-07T05:31:56Z",
"void_reason": "Imported the incorrect workbook.",
"created_checks": [
{
"id": 120,
"scheduled_for": "2026-10-20",
"status": "submitted",
"revision": 1,
"site": {
"id": 12,
"name": "Main campus"
},
"cohort": {
"id": 12,
"name": "Main campus"
},
"counts": {
"expected": 25,
"seen": 23,
"unresolved": 2
}
}
],
"rows": {
"items": [
{
"id": 84,
"sheet": "Sheet1",
"source_row_number": 2,
"attendance_date": "2026-10-20",
"display_name": "Jane Recipient",
"gratona_id": "42",
"external_student_id": "STU-001",
"site_id": 12,
"cohort_id": 18,
"site_source_value": "Main campus",
"cohort_source_value": "Group A",
"symbol": "P",
"encounter_status": "seen",
"enrollment_confirmation": "confirmed_enrolled",
"match_type": "suggested_candidate",
"decision": "match",
"status": "review",
"entity_id": 42,
"candidates": [
{
"entity_id": 42,
"gratona_id": 42,
"display_name": "Jane Recipient",
"site_id": 12,
"cohort_id": 18,
"score": 95,
"agreed": [
"name"
],
"conflicted": [
"gender"
]
}
],
"errors": [
"placement_conflict"
],
"warnings": [
"candidate_confirmation_required"
],
"participation_session_id": 120
}
],
"total": 25,
"current_page": 1,
"per_page": 50,
"last_page": 1
},
"recipient_fields": [
{
"key": "student_id",
"label": "Student ID",
"type": "hysCustomID",
"is_title": false
}
]
}
}{
"message": "Unauthorized",
"status": "error"
}{
"message": "Not Found",
"status": "error"
}{
"errors": {},
"status": "error",
"message": "The given data was invalid."
}