Events
Preview invitation tasks for an invitee
Requires an event start and saved plan. Resolves selected enabled steps, due dates and assignees, counts mapped versus new tasks, and sends no communication. Dates must be today/future in event timezone; assignees must access both event and donor. Requires event view capability and organization/donor visibility. Also requires task view permission.
POST
/
admin
/
events
/
{eventId}
/
invitees
/
{inviteeId}
/
plan-preview
Preview invitation tasks for an invitee
curl --request POST \
--url https://api.gratona.com/v1/admin/events/{eventId}/invitees/{inviteeId}/plan-preview \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"steps": [
{
"step_key": "personal_call",
"enabled": true,
"due_date": "2026-11-01",
"assignee_strategy": "invitee_owner",
"assignee_user_id": 42
}
]
}
'import requests
url = "https://api.gratona.com/v1/admin/events/{eventId}/invitees/{inviteeId}/plan-preview"
payload = { "steps": [
{
"step_key": "personal_call",
"enabled": True,
"due_date": "2026-11-01",
"assignee_strategy": "invitee_owner",
"assignee_user_id": 42
}
] }
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({
steps: [
{
step_key: 'personal_call',
enabled: true,
due_date: '2026-11-01',
assignee_strategy: 'invitee_owner',
assignee_user_id: 42
}
]
})
};
fetch('https://api.gratona.com/v1/admin/events/{eventId}/invitees/{inviteeId}/plan-preview', 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/events/{eventId}/invitees/{inviteeId}/plan-preview",
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([
'steps' => [
[
'step_key' => 'personal_call',
'enabled' => true,
'due_date' => '2026-11-01',
'assignee_strategy' => 'invitee_owner',
'assignee_user_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/events/{eventId}/invitees/{inviteeId}/plan-preview"
payload := strings.NewReader("{\n \"steps\": [\n {\n \"step_key\": \"personal_call\",\n \"enabled\": true,\n \"due_date\": \"2026-11-01\",\n \"assignee_strategy\": \"invitee_owner\",\n \"assignee_user_id\": 42\n }\n ]\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/events/{eventId}/invitees/{inviteeId}/plan-preview")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"steps\": [\n {\n \"step_key\": \"personal_call\",\n \"enabled\": true,\n \"due_date\": \"2026-11-01\",\n \"assignee_strategy\": \"invitee_owner\",\n \"assignee_user_id\": 42\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gratona.com/v1/admin/events/{eventId}/invitees/{inviteeId}/plan-preview")
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 \"steps\": [\n {\n \"step_key\": \"personal_call\",\n \"enabled\": true,\n \"due_date\": \"2026-11-01\",\n \"assignee_strategy\": \"invitee_owner\",\n \"assignee_user_id\": 42\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"data": {
"invitee_id": 42,
"invitee_version": 1,
"plan": {
"materialized": false,
"id": 42,
"name": "Personal invitation",
"revision": 1,
"lock_version": 1,
"source_preset_key": "personal_invitation_v1",
"source_preset_version": 42,
"definition_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"steps": [
{
"id": 42,
"step_key": "personal_call",
"position": 42,
"label": "Personal call",
"task_title_template": "Call {donor_name} about {event_name}",
"invitation_method": "phone_call",
"days_before_event": 28,
"assignee_strategy": "invitee_owner",
"assignee_user_id": 42,
"is_enabled": true
}
]
},
"steps": [
{
"step_key": "personal_call",
"label": "Personal call",
"task_title_template": "Call {donor_name} about {event_name}",
"invitation_method": "phone_call",
"days_before_event": 28,
"due_date": "2026-11-01",
"assignee_strategy": "invitee_owner",
"resolved_assignee_user_id": 42,
"assignee_user_id": 42,
"enabled": false
}
],
"new_task_count": 42,
"existing_task_count": 42,
"notice": "This creates staff tasks. It does not contact invitees."
}
}{
"message": "Something went wrong. Please try again.",
"status": "error",
"error": "invalid_request",
"code": "DONOR_NOT_FOUND"
}{
"message": "Something went wrong. Please try again.",
"status": "error",
"error": "invalid_request",
"code": "DONOR_NOT_FOUND"
}{
"message": "Not Found",
"status": "error"
}{
"message": "Version, idempotency, preview or archived-event conflict.",
"error_code": "event_invitee_conflict",
"details": {
"current_version": 42,
"current_lock_version": 42,
"current_revision": 42,
"current_definition_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
}{
"errors": {},
"status": "error",
"message": "The given data was invalid."
}Authorizations
bearerAuthapiKeyAuth
Passport bearer token authentication for legacy admin sessions.
Path Parameters
Record ID in the authenticated organization.
Example:
42
Record ID in the authenticated organization.
Example:
42
Body
application/json
Minimum array length:
1Show child attributes
Show child attributes
Response
Preview invitation tasks for an invitee completed.
Show child attributes
Show child attributes
⌘I
Preview invitation tasks for an invitee
curl --request POST \
--url https://api.gratona.com/v1/admin/events/{eventId}/invitees/{inviteeId}/plan-preview \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"steps": [
{
"step_key": "personal_call",
"enabled": true,
"due_date": "2026-11-01",
"assignee_strategy": "invitee_owner",
"assignee_user_id": 42
}
]
}
'import requests
url = "https://api.gratona.com/v1/admin/events/{eventId}/invitees/{inviteeId}/plan-preview"
payload = { "steps": [
{
"step_key": "personal_call",
"enabled": True,
"due_date": "2026-11-01",
"assignee_strategy": "invitee_owner",
"assignee_user_id": 42
}
] }
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({
steps: [
{
step_key: 'personal_call',
enabled: true,
due_date: '2026-11-01',
assignee_strategy: 'invitee_owner',
assignee_user_id: 42
}
]
})
};
fetch('https://api.gratona.com/v1/admin/events/{eventId}/invitees/{inviteeId}/plan-preview', 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/events/{eventId}/invitees/{inviteeId}/plan-preview",
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([
'steps' => [
[
'step_key' => 'personal_call',
'enabled' => true,
'due_date' => '2026-11-01',
'assignee_strategy' => 'invitee_owner',
'assignee_user_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/events/{eventId}/invitees/{inviteeId}/plan-preview"
payload := strings.NewReader("{\n \"steps\": [\n {\n \"step_key\": \"personal_call\",\n \"enabled\": true,\n \"due_date\": \"2026-11-01\",\n \"assignee_strategy\": \"invitee_owner\",\n \"assignee_user_id\": 42\n }\n ]\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/events/{eventId}/invitees/{inviteeId}/plan-preview")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"steps\": [\n {\n \"step_key\": \"personal_call\",\n \"enabled\": true,\n \"due_date\": \"2026-11-01\",\n \"assignee_strategy\": \"invitee_owner\",\n \"assignee_user_id\": 42\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gratona.com/v1/admin/events/{eventId}/invitees/{inviteeId}/plan-preview")
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 \"steps\": [\n {\n \"step_key\": \"personal_call\",\n \"enabled\": true,\n \"due_date\": \"2026-11-01\",\n \"assignee_strategy\": \"invitee_owner\",\n \"assignee_user_id\": 42\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"data": {
"invitee_id": 42,
"invitee_version": 1,
"plan": {
"materialized": false,
"id": 42,
"name": "Personal invitation",
"revision": 1,
"lock_version": 1,
"source_preset_key": "personal_invitation_v1",
"source_preset_version": 42,
"definition_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"steps": [
{
"id": 42,
"step_key": "personal_call",
"position": 42,
"label": "Personal call",
"task_title_template": "Call {donor_name} about {event_name}",
"invitation_method": "phone_call",
"days_before_event": 28,
"assignee_strategy": "invitee_owner",
"assignee_user_id": 42,
"is_enabled": true
}
]
},
"steps": [
{
"step_key": "personal_call",
"label": "Personal call",
"task_title_template": "Call {donor_name} about {event_name}",
"invitation_method": "phone_call",
"days_before_event": 28,
"due_date": "2026-11-01",
"assignee_strategy": "invitee_owner",
"resolved_assignee_user_id": 42,
"assignee_user_id": 42,
"enabled": false
}
],
"new_task_count": 42,
"existing_task_count": 42,
"notice": "This creates staff tasks. It does not contact invitees."
}
}{
"message": "Something went wrong. Please try again.",
"status": "error",
"error": "invalid_request",
"code": "DONOR_NOT_FOUND"
}{
"message": "Something went wrong. Please try again.",
"status": "error",
"error": "invalid_request",
"code": "DONOR_NOT_FOUND"
}{
"message": "Not Found",
"status": "error"
}{
"message": "Version, idempotency, preview or archived-event conflict.",
"error_code": "event_invitee_conflict",
"details": {
"current_version": 42,
"current_lock_version": 42,
"current_revision": 42,
"current_definition_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
}{
"errors": {},
"status": "error",
"message": "The given data was invalid."
}