Check a mailing generation audience
Resolves the source-specific audience and classifies every record ready/warning/skipped without creating a run. Custom print mail skips postal opt-outs and master communication pauses; tax summaries also require a ready contribution statement. Label data decides address warnings/skips. Returns all counts plus one preflight page (default 20/max 100). Custom templates support only delivery_mode=none; email modes are reserved for system Tax Summary mailings. Requires permission: one of mailings_manage, manage_email.
curl --request POST \
--url https://api.gratona.com/v1/admin/mailing_templates/{id}/preflight \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"source_type": "donor_rows",
"selection": {
"donor_ids": [
42
],
"hysform_id": 42,
"donor_entity_ids": [
42
],
"program_ids": [
42
],
"program_id": 42,
"filter": false,
"status": "current",
"query": "Jane",
"savedFilterId": 42,
"filterGroups": [
{}
],
"fields": [
"<unknown>"
],
"year": 2026,
"household_id": 42,
"include_soft_credits": false,
"recipients": [
"jane@example.org"
]
},
"delivery_mode": "none",
"label_layout_preset": "single_label",
"labels_per_sheet": 2,
"border_labels": true,
"preflight_page": 1,
"preflight_per_page": 20
}
'import requests
url = "https://api.gratona.com/v1/admin/mailing_templates/{id}/preflight"
payload = {
"source_type": "donor_rows",
"selection": {
"donor_ids": [42],
"hysform_id": 42,
"donor_entity_ids": [42],
"program_ids": [42],
"program_id": 42,
"filter": False,
"status": "current",
"query": "Jane",
"savedFilterId": 42,
"filterGroups": [{}],
"fields": ["<unknown>"],
"year": 2026,
"household_id": 42,
"include_soft_credits": False,
"recipients": ["jane@example.org"]
},
"delivery_mode": "none",
"label_layout_preset": "single_label",
"labels_per_sheet": 2,
"border_labels": True,
"preflight_page": 1,
"preflight_per_page": 20
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
source_type: 'donor_rows',
selection: {
donor_ids: [42],
hysform_id: 42,
donor_entity_ids: [42],
program_ids: [42],
program_id: 42,
filter: false,
status: 'current',
query: 'Jane',
savedFilterId: 42,
filterGroups: [{}],
fields: ['<unknown>'],
year: 2026,
household_id: 42,
include_soft_credits: false,
recipients: ['jane@example.org']
},
delivery_mode: 'none',
label_layout_preset: 'single_label',
labels_per_sheet: 2,
border_labels: true,
preflight_page: 1,
preflight_per_page: 20
})
};
fetch('https://api.gratona.com/v1/admin/mailing_templates/{id}/preflight', 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/mailing_templates/{id}/preflight",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'source_type' => 'donor_rows',
'selection' => [
'donor_ids' => [
42
],
'hysform_id' => 42,
'donor_entity_ids' => [
42
],
'program_ids' => [
42
],
'program_id' => 42,
'filter' => false,
'status' => 'current',
'query' => 'Jane',
'savedFilterId' => 42,
'filterGroups' => [
[
]
],
'fields' => [
'<unknown>'
],
'year' => 2026,
'household_id' => 42,
'include_soft_credits' => false,
'recipients' => [
'jane@example.org'
]
],
'delivery_mode' => 'none',
'label_layout_preset' => 'single_label',
'labels_per_sheet' => 2,
'border_labels' => true,
'preflight_page' => 1,
'preflight_per_page' => 20
]),
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/mailing_templates/{id}/preflight"
payload := strings.NewReader("{\n \"source_type\": \"donor_rows\",\n \"selection\": {\n \"donor_ids\": [\n 42\n ],\n \"hysform_id\": 42,\n \"donor_entity_ids\": [\n 42\n ],\n \"program_ids\": [\n 42\n ],\n \"program_id\": 42,\n \"filter\": false,\n \"status\": \"current\",\n \"query\": \"Jane\",\n \"savedFilterId\": 42,\n \"filterGroups\": [\n {}\n ],\n \"fields\": [\n \"<unknown>\"\n ],\n \"year\": 2026,\n \"household_id\": 42,\n \"include_soft_credits\": false,\n \"recipients\": [\n \"jane@example.org\"\n ]\n },\n \"delivery_mode\": \"none\",\n \"label_layout_preset\": \"single_label\",\n \"labels_per_sheet\": 2,\n \"border_labels\": true,\n \"preflight_page\": 1,\n \"preflight_per_page\": 20\n}")
req, _ := http.NewRequest("POST", 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.post("https://api.gratona.com/v1/admin/mailing_templates/{id}/preflight")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"source_type\": \"donor_rows\",\n \"selection\": {\n \"donor_ids\": [\n 42\n ],\n \"hysform_id\": 42,\n \"donor_entity_ids\": [\n 42\n ],\n \"program_ids\": [\n 42\n ],\n \"program_id\": 42,\n \"filter\": false,\n \"status\": \"current\",\n \"query\": \"Jane\",\n \"savedFilterId\": 42,\n \"filterGroups\": [\n {}\n ],\n \"fields\": [\n \"<unknown>\"\n ],\n \"year\": 2026,\n \"household_id\": 42,\n \"include_soft_credits\": false,\n \"recipients\": [\n \"jane@example.org\"\n ]\n },\n \"delivery_mode\": \"none\",\n \"label_layout_preset\": \"single_label\",\n \"labels_per_sheet\": 2,\n \"border_labels\": true,\n \"preflight_page\": 1,\n \"preflight_per_page\": 20\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gratona.com/v1/admin/mailing_templates/{id}/preflight")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"source_type\": \"donor_rows\",\n \"selection\": {\n \"donor_ids\": [\n 42\n ],\n \"hysform_id\": 42,\n \"donor_entity_ids\": [\n 42\n ],\n \"program_ids\": [\n 42\n ],\n \"program_id\": 42,\n \"filter\": false,\n \"status\": \"current\",\n \"query\": \"Jane\",\n \"savedFilterId\": 42,\n \"filterGroups\": [\n {}\n ],\n \"fields\": [\n \"<unknown>\"\n ],\n \"year\": 2026,\n \"household_id\": 42,\n \"include_soft_credits\": false,\n \"recipients\": [\n \"jane@example.org\"\n ]\n },\n \"delivery_mode\": \"none\",\n \"label_layout_preset\": \"single_label\",\n \"labels_per_sheet\": 2,\n \"border_labels\": true,\n \"preflight_page\": 1,\n \"preflight_per_page\": 20\n}"
response = http.request(request)
puts response.read_body{
"data": {
"counts": {
"ready": 1,
"warning": 1,
"skipped": 1
},
"items": [
{
"recipient_name": "Example",
"status": "ready",
"skip_reason": "Example",
"warnings": [
"<string>"
]
}
],
"total_items": 1,
"pagination": {
"page": 1,
"per_page": 1,
"returned_items": 1,
"total_items": 1,
"total_pages": 1,
"has_more": true,
"next_page": 2
},
"selected_program_ids": [
42
],
"label_layout": {
"selected_layout_preset": "a4_sheet",
"selected_layout_label": "Example",
"labels_per_sheet": 1,
"estimated_printable_items": 1,
"estimated_sheet_count": 1,
"border_labels": true
}
}
}{
"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
Id in the current organization.
Body
Validated request fields for this operation.
Source type. Validation: required; allowed values: donor_rows, donor_filter, sponsorship_rows, all_sponsorships, tax_summary.
donor_rows, donor_filter, sponsorship_rows, all_sponsorships, tax_summary "donor_rows"
Source-specific audience options. Additional donor/relationship worksheet filter keys are forwarded unchanged; ids are resolved inside the current organization.
Show child attributes
Show child attributes
Defaults none; non-none is permitted only for the system tax_summary renderer.
none, email_admin, email_selected_donors, email_explicit, null "none"
Label layout preset. Validation: nullable; allowed values: single_label, a4_sheet, a3_sheet, letter_85x11_1_up, letter_4x2_10_up, letter_2625x1_30_up, letter_3x2_10_up.
single_label, a4_sheet, a3_sheet, letter_85x11_1_up, letter_4x2_10_up, letter_2625x1_30_up, letter_3x2_10_up, null "single_label"
Labels per sheet. Validation: nullable, integer; allowed values: 2, 4, 6, 8, 10, 12, 14, 16.
2, 4, 6, 8, 10, 12, 14, 16, null 2
Border labels. Validation: nullable, boolean.
true
Preflight page. Validation: nullable, integer, min:1.
x >= 11
Preflight per page. Validation: nullable, integer, min:1, max:100.
1 <= x <= 10020
Response
Operation result.
All audience records are classified; only the preflight items list is paginated (default 20, maximum 100). Label summary is null without a label document.
Show child attributes
Show child attributes
curl --request POST \
--url https://api.gratona.com/v1/admin/mailing_templates/{id}/preflight \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"source_type": "donor_rows",
"selection": {
"donor_ids": [
42
],
"hysform_id": 42,
"donor_entity_ids": [
42
],
"program_ids": [
42
],
"program_id": 42,
"filter": false,
"status": "current",
"query": "Jane",
"savedFilterId": 42,
"filterGroups": [
{}
],
"fields": [
"<unknown>"
],
"year": 2026,
"household_id": 42,
"include_soft_credits": false,
"recipients": [
"jane@example.org"
]
},
"delivery_mode": "none",
"label_layout_preset": "single_label",
"labels_per_sheet": 2,
"border_labels": true,
"preflight_page": 1,
"preflight_per_page": 20
}
'import requests
url = "https://api.gratona.com/v1/admin/mailing_templates/{id}/preflight"
payload = {
"source_type": "donor_rows",
"selection": {
"donor_ids": [42],
"hysform_id": 42,
"donor_entity_ids": [42],
"program_ids": [42],
"program_id": 42,
"filter": False,
"status": "current",
"query": "Jane",
"savedFilterId": 42,
"filterGroups": [{}],
"fields": ["<unknown>"],
"year": 2026,
"household_id": 42,
"include_soft_credits": False,
"recipients": ["jane@example.org"]
},
"delivery_mode": "none",
"label_layout_preset": "single_label",
"labels_per_sheet": 2,
"border_labels": True,
"preflight_page": 1,
"preflight_per_page": 20
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
source_type: 'donor_rows',
selection: {
donor_ids: [42],
hysform_id: 42,
donor_entity_ids: [42],
program_ids: [42],
program_id: 42,
filter: false,
status: 'current',
query: 'Jane',
savedFilterId: 42,
filterGroups: [{}],
fields: ['<unknown>'],
year: 2026,
household_id: 42,
include_soft_credits: false,
recipients: ['jane@example.org']
},
delivery_mode: 'none',
label_layout_preset: 'single_label',
labels_per_sheet: 2,
border_labels: true,
preflight_page: 1,
preflight_per_page: 20
})
};
fetch('https://api.gratona.com/v1/admin/mailing_templates/{id}/preflight', 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/mailing_templates/{id}/preflight",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'source_type' => 'donor_rows',
'selection' => [
'donor_ids' => [
42
],
'hysform_id' => 42,
'donor_entity_ids' => [
42
],
'program_ids' => [
42
],
'program_id' => 42,
'filter' => false,
'status' => 'current',
'query' => 'Jane',
'savedFilterId' => 42,
'filterGroups' => [
[
]
],
'fields' => [
'<unknown>'
],
'year' => 2026,
'household_id' => 42,
'include_soft_credits' => false,
'recipients' => [
'jane@example.org'
]
],
'delivery_mode' => 'none',
'label_layout_preset' => 'single_label',
'labels_per_sheet' => 2,
'border_labels' => true,
'preflight_page' => 1,
'preflight_per_page' => 20
]),
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/mailing_templates/{id}/preflight"
payload := strings.NewReader("{\n \"source_type\": \"donor_rows\",\n \"selection\": {\n \"donor_ids\": [\n 42\n ],\n \"hysform_id\": 42,\n \"donor_entity_ids\": [\n 42\n ],\n \"program_ids\": [\n 42\n ],\n \"program_id\": 42,\n \"filter\": false,\n \"status\": \"current\",\n \"query\": \"Jane\",\n \"savedFilterId\": 42,\n \"filterGroups\": [\n {}\n ],\n \"fields\": [\n \"<unknown>\"\n ],\n \"year\": 2026,\n \"household_id\": 42,\n \"include_soft_credits\": false,\n \"recipients\": [\n \"jane@example.org\"\n ]\n },\n \"delivery_mode\": \"none\",\n \"label_layout_preset\": \"single_label\",\n \"labels_per_sheet\": 2,\n \"border_labels\": true,\n \"preflight_page\": 1,\n \"preflight_per_page\": 20\n}")
req, _ := http.NewRequest("POST", 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.post("https://api.gratona.com/v1/admin/mailing_templates/{id}/preflight")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"source_type\": \"donor_rows\",\n \"selection\": {\n \"donor_ids\": [\n 42\n ],\n \"hysform_id\": 42,\n \"donor_entity_ids\": [\n 42\n ],\n \"program_ids\": [\n 42\n ],\n \"program_id\": 42,\n \"filter\": false,\n \"status\": \"current\",\n \"query\": \"Jane\",\n \"savedFilterId\": 42,\n \"filterGroups\": [\n {}\n ],\n \"fields\": [\n \"<unknown>\"\n ],\n \"year\": 2026,\n \"household_id\": 42,\n \"include_soft_credits\": false,\n \"recipients\": [\n \"jane@example.org\"\n ]\n },\n \"delivery_mode\": \"none\",\n \"label_layout_preset\": \"single_label\",\n \"labels_per_sheet\": 2,\n \"border_labels\": true,\n \"preflight_page\": 1,\n \"preflight_per_page\": 20\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gratona.com/v1/admin/mailing_templates/{id}/preflight")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"source_type\": \"donor_rows\",\n \"selection\": {\n \"donor_ids\": [\n 42\n ],\n \"hysform_id\": 42,\n \"donor_entity_ids\": [\n 42\n ],\n \"program_ids\": [\n 42\n ],\n \"program_id\": 42,\n \"filter\": false,\n \"status\": \"current\",\n \"query\": \"Jane\",\n \"savedFilterId\": 42,\n \"filterGroups\": [\n {}\n ],\n \"fields\": [\n \"<unknown>\"\n ],\n \"year\": 2026,\n \"household_id\": 42,\n \"include_soft_credits\": false,\n \"recipients\": [\n \"jane@example.org\"\n ]\n },\n \"delivery_mode\": \"none\",\n \"label_layout_preset\": \"single_label\",\n \"labels_per_sheet\": 2,\n \"border_labels\": true,\n \"preflight_page\": 1,\n \"preflight_per_page\": 20\n}"
response = http.request(request)
puts response.read_body{
"data": {
"counts": {
"ready": 1,
"warning": 1,
"skipped": 1
},
"items": [
{
"recipient_name": "Example",
"status": "ready",
"skip_reason": "Example",
"warnings": [
"<string>"
]
}
],
"total_items": 1,
"pagination": {
"page": 1,
"per_page": 1,
"returned_items": 1,
"total_items": 1,
"total_pages": 1,
"has_more": true,
"next_page": 2
},
"selected_program_ids": [
42
],
"label_layout": {
"selected_layout_preset": "a4_sheet",
"selected_layout_label": "Example",
"labels_per_sheet": 1,
"estimated_printable_items": 1,
"estimated_sheet_count": 1,
"border_labels": true
}
}
}{
"message": "Unauthorized",
"status": "error"
}{
"message": "Not Found",
"status": "error"
}{
"errors": {},
"status": "error",
"message": "The given data was invalid."
}