Validate photo uploads before import
Creates or reuses a file validation job for staged photo imports without persisting uploads to recipient or donor records. The endpoint can validate direct multipart files or files already staged in an upload session. Requires admin file access through user.permissions.
curl --request POST \
--url https://api.gratona.com/v1/admin/import_files/{program_id}/validate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form type=entity \
--form unique_field=hys_id \
--form is_profile_photo=false \
--form upload_session_id=01HV7W4XW4N8Z3J7A2Y4C9R6K1 \
--form 'files=<string>'import requests
url = "https://api.gratona.com/v1/admin/import_files/{program_id}/validate"
payload = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\nentity\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"unique_field\"\r\n\r\nhys_id\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"is_profile_photo\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"upload_session_id\"\r\n\r\n01HV7W4XW4N8Z3J7A2Y4C9R6K1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"\r\n\r\n<string>\r\n-----011000010111000001101001--"
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "multipart/form-data"
}
response = requests.post(url, data=payload, headers=headers)
print(response.text)const form = new FormData();
form.append('type', 'entity');
form.append('unique_field', 'hys_id');
form.append('is_profile_photo', 'false');
form.append('upload_session_id', '01HV7W4XW4N8Z3J7A2Y4C9R6K1');
form.append('files', '<string>');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://api.gratona.com/v1/admin/import_files/{program_id}/validate', 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/import_files/{program_id}/validate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\nentity\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"unique_field\"\r\n\r\nhys_id\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"is_profile_photo\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"upload_session_id\"\r\n\r\n01HV7W4XW4N8Z3J7A2Y4C9R6K1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"\r\n\r\n<string>\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$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/import_files/{program_id}/validate"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\nentity\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"unique_field\"\r\n\r\nhys_id\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"is_profile_photo\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"upload_session_id\"\r\n\r\n01HV7W4XW4N8Z3J7A2Y4C9R6K1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"\r\n\r\n<string>\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.gratona.com/v1/admin/import_files/{program_id}/validate")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\nentity\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"unique_field\"\r\n\r\nhys_id\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"is_profile_photo\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"upload_session_id\"\r\n\r\n01HV7W4XW4N8Z3J7A2Y4C9R6K1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"\r\n\r\n<string>\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gratona.com/v1/admin/import_files/{program_id}/validate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\nentity\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"unique_field\"\r\n\r\nhys_id\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"is_profile_photo\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"upload_session_id\"\r\n\r\n01HV7W4XW4N8Z3J7A2Y4C9R6K1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"\r\n\r\n<string>\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"message": "File validation has been queued.",
"validation_job_id": 123
}{
"errors": {},
"status": "error",
"message": "The given data was invalid."
}{
"message": "Something went wrong. Please try again.",
"status": "error",
"error": "invalid_request",
"code": "DONOR_NOT_FOUND"
}Authorizations
Passport bearer token authentication for legacy admin sessions.
Path Parameters
Required program ID used to scope validation and later processing for the current client.
Body
Required string. Identifies whether files should later attach to recipients or donors.
entity, donor "entity"
Required string. Field key used by validation to match file names or CSV data to records.
"hys_id"
Required boolean-like value. Indicates whether validated photos should become profile photos during processing.
true, false, 0, 1 "false"
Nullable string. When present, claims files from an import upload session instead of reading multipart files.
"01HV7W4XW4N8Z3J7A2Y4C9R6K1"
Multipart photo uploads required when upload_session_id is not supplied.
curl --request POST \
--url https://api.gratona.com/v1/admin/import_files/{program_id}/validate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form type=entity \
--form unique_field=hys_id \
--form is_profile_photo=false \
--form upload_session_id=01HV7W4XW4N8Z3J7A2Y4C9R6K1 \
--form 'files=<string>'import requests
url = "https://api.gratona.com/v1/admin/import_files/{program_id}/validate"
payload = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\nentity\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"unique_field\"\r\n\r\nhys_id\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"is_profile_photo\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"upload_session_id\"\r\n\r\n01HV7W4XW4N8Z3J7A2Y4C9R6K1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"\r\n\r\n<string>\r\n-----011000010111000001101001--"
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "multipart/form-data"
}
response = requests.post(url, data=payload, headers=headers)
print(response.text)const form = new FormData();
form.append('type', 'entity');
form.append('unique_field', 'hys_id');
form.append('is_profile_photo', 'false');
form.append('upload_session_id', '01HV7W4XW4N8Z3J7A2Y4C9R6K1');
form.append('files', '<string>');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://api.gratona.com/v1/admin/import_files/{program_id}/validate', 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/import_files/{program_id}/validate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\nentity\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"unique_field\"\r\n\r\nhys_id\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"is_profile_photo\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"upload_session_id\"\r\n\r\n01HV7W4XW4N8Z3J7A2Y4C9R6K1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"\r\n\r\n<string>\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$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/import_files/{program_id}/validate"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\nentity\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"unique_field\"\r\n\r\nhys_id\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"is_profile_photo\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"upload_session_id\"\r\n\r\n01HV7W4XW4N8Z3J7A2Y4C9R6K1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"\r\n\r\n<string>\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.gratona.com/v1/admin/import_files/{program_id}/validate")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\nentity\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"unique_field\"\r\n\r\nhys_id\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"is_profile_photo\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"upload_session_id\"\r\n\r\n01HV7W4XW4N8Z3J7A2Y4C9R6K1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"\r\n\r\n<string>\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gratona.com/v1/admin/import_files/{program_id}/validate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\nentity\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"unique_field\"\r\n\r\nhys_id\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"is_profile_photo\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"upload_session_id\"\r\n\r\n01HV7W4XW4N8Z3J7A2Y4C9R6K1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"\r\n\r\n<string>\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"message": "File validation has been queued.",
"validation_job_id": 123
}{
"errors": {},
"status": "error",
"message": "The given data was invalid."
}{
"message": "Something went wrong. Please try again.",
"status": "error",
"error": "invalid_request",
"code": "DONOR_NOT_FOUND"
}