Create a household from two donor records
Creates an active household from distinct primary and related donors, both active in this organization and outside any household. Stores the related donor relationship and optional primary relationship, address and custom fields. Material stewardship impact returns 409 with an expiring confirmation token and required contact/archive repairs; resubmit the same reviewed change with plan_impact_version and plan_repairs.
curl --request POST \
--url https://api.gratona.com/v1/admin/households/create-from-donor \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"primary_contact_id": 42,
"household_name": "Doe household",
"donor_id": 42,
"household_relationship": "Church",
"primary_relationship": "Church",
"address": {
"line1": "10 Main Street",
"line2": "Apt 2",
"city": "Kampala",
"state": "Central",
"postal_code": "00000",
"country": "Uganda"
},
"json_fields": {},
"plan_impact_version": "issued-household-impact-version",
"plan_repairs": [
{
"plan_id": 42,
"action": "replace_action_donor",
"action_donor_id": 42,
"reason": "Household is being removed."
}
]
}
'import requests
url = "https://api.gratona.com/v1/admin/households/create-from-donor"
payload = {
"primary_contact_id": 42,
"household_name": "Doe household",
"donor_id": 42,
"household_relationship": "Church",
"primary_relationship": "Church",
"address": {
"line1": "10 Main Street",
"line2": "Apt 2",
"city": "Kampala",
"state": "Central",
"postal_code": "00000",
"country": "Uganda"
},
"json_fields": {},
"plan_impact_version": "issued-household-impact-version",
"plan_repairs": [
{
"plan_id": 42,
"action": "replace_action_donor",
"action_donor_id": 42,
"reason": "Household is being removed."
}
]
}
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({
primary_contact_id: 42,
household_name: 'Doe household',
donor_id: 42,
household_relationship: 'Church',
primary_relationship: 'Church',
address: {
line1: '10 Main Street',
line2: 'Apt 2',
city: 'Kampala',
state: 'Central',
postal_code: '00000',
country: 'Uganda'
},
json_fields: {},
plan_impact_version: 'issued-household-impact-version',
plan_repairs: [
{
plan_id: 42,
action: 'replace_action_donor',
action_donor_id: 42,
reason: 'Household is being removed.'
}
]
})
};
fetch('https://api.gratona.com/v1/admin/households/create-from-donor', 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/households/create-from-donor",
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([
'primary_contact_id' => 42,
'household_name' => 'Doe household',
'donor_id' => 42,
'household_relationship' => 'Church',
'primary_relationship' => 'Church',
'address' => [
'line1' => '10 Main Street',
'line2' => 'Apt 2',
'city' => 'Kampala',
'state' => 'Central',
'postal_code' => '00000',
'country' => 'Uganda'
],
'json_fields' => [
],
'plan_impact_version' => 'issued-household-impact-version',
'plan_repairs' => [
[
'plan_id' => 42,
'action' => 'replace_action_donor',
'action_donor_id' => 42,
'reason' => 'Household is being removed.'
]
]
]),
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/households/create-from-donor"
payload := strings.NewReader("{\n \"primary_contact_id\": 42,\n \"household_name\": \"Doe household\",\n \"donor_id\": 42,\n \"household_relationship\": \"Church\",\n \"primary_relationship\": \"Church\",\n \"address\": {\n \"line1\": \"10 Main Street\",\n \"line2\": \"Apt 2\",\n \"city\": \"Kampala\",\n \"state\": \"Central\",\n \"postal_code\": \"00000\",\n \"country\": \"Uganda\"\n },\n \"json_fields\": {},\n \"plan_impact_version\": \"issued-household-impact-version\",\n \"plan_repairs\": [\n {\n \"plan_id\": 42,\n \"action\": \"replace_action_donor\",\n \"action_donor_id\": 42,\n \"reason\": \"Household is being removed.\"\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/households/create-from-donor")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"primary_contact_id\": 42,\n \"household_name\": \"Doe household\",\n \"donor_id\": 42,\n \"household_relationship\": \"Church\",\n \"primary_relationship\": \"Church\",\n \"address\": {\n \"line1\": \"10 Main Street\",\n \"line2\": \"Apt 2\",\n \"city\": \"Kampala\",\n \"state\": \"Central\",\n \"postal_code\": \"00000\",\n \"country\": \"Uganda\"\n },\n \"json_fields\": {},\n \"plan_impact_version\": \"issued-household-impact-version\",\n \"plan_repairs\": [\n {\n \"plan_id\": 42,\n \"action\": \"replace_action_donor\",\n \"action_donor_id\": 42,\n \"reason\": \"Household is being removed.\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gratona.com/v1/admin/households/create-from-donor")
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 \"primary_contact_id\": 42,\n \"household_name\": \"Doe household\",\n \"donor_id\": 42,\n \"household_relationship\": \"Church\",\n \"primary_relationship\": \"Church\",\n \"address\": {\n \"line1\": \"10 Main Street\",\n \"line2\": \"Apt 2\",\n \"city\": \"Kampala\",\n \"state\": \"Central\",\n \"postal_code\": \"00000\",\n \"country\": \"Uganda\"\n },\n \"json_fields\": {},\n \"plan_impact_version\": \"issued-household-impact-version\",\n \"plan_repairs\": [\n {\n \"plan_id\": 42,\n \"action\": \"replace_action_donor\",\n \"action_donor_id\": 42,\n \"reason\": \"Household is being removed.\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"message": "Household created successfully with related donor",
"household": {
"id": 42,
"name": "Doe household",
"donor_ids": [
42
],
"primary_contact": {
"id": 42,
"name": "Jane Doe"
},
"related_donor": {
"id": 42,
"name": "Jane Doe",
"relationship": "Example"
}
}
}{
"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"
}{
"status": "error",
"code": "PLAN_IMPACT_CONFIRMATION_REQUIRED",
"message": "Review household plan impact before saving.",
"data": {
"material_impact": false,
"affected_plans": [
{
"id": 42,
"subject": {
"type": "donor",
"id": 42
},
"stage": "qualifying",
"status": "draft",
"period": {
"start": "2026-10-20",
"end": "2026-10-20"
},
"version": 2,
"action_donor_id": 42,
"scope_version": 2
}
],
"group_plans": [
"<string>"
],
"transfer_candidates": [
"<string>"
],
"scope_changes": [
{
"plan_id": 42,
"next_members": [
{
"member_type": "donor",
"member_id": 42,
"scope_role": "core"
}
],
"eligible_action_donor_ids": [
42
],
"invalid_open_move_ids": [
42
]
}
],
"eligible_action_donor_ids": [
42
],
"collisions": [
{
"plan_id": 42,
"conflicting_plan": {}
}
],
"authority_changes": [
"<string>"
],
"required_repairs": [
{
"plan_id": 42,
"choices": [
"replace_action_donor"
],
"eligible_action_donor_ids": [
42
],
"recommended_action_donor_id": 42
}
],
"proposed_member_donor_ids": [
42
],
"primary_contact_id": 42,
"plan_repairs": [
{
"plan_id": 42
}
],
"command": "household_membership",
"expires_at": "2026-10-20T12:00:00Z",
"impact_version": "issued-household-impact-version",
"conflicts": [
{
"plan_id": 42,
"conflicting_plan": {}
}
]
}
}{
"errors": {},
"status": "error",
"message": "The given data was invalid."
}{
"success": false,
"message": "Failed to update household",
"error": "Unable to complete household change."
}Authorizations
Passport bearer token authentication for legacy admin sessions.
Body
Active primary donor.
42
Required household label.
"Doe household"
Distinct active related donor.
42
Household relationship label.
Church, Employer, Employee, Friend, Director, Associate, Child, Parent, Grandparent, Grandchild, Relative, Spouse, Sibling, Designated Registrant, Registrant, Church Member, Partner, Organization, Member, Beneficiary, Sponsor "Church"
Household relationship label.
Church, Employer, Employee, Friend, Director, Associate, Child, Parent, Grandparent, Grandchild, Relative, Spouse, Sibling, Designated Registrant, Registrant, Church Member, Partner, Organization, Member, Beneficiary, Sponsor, null "Church"
Show child attributes
Show child attributes
Household custom values.
Token from a 409 stewardship impact response; required when open plan impact is material.
4096"issued-household-impact-version"
Show child attributes
Show child attributes
curl --request POST \
--url https://api.gratona.com/v1/admin/households/create-from-donor \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"primary_contact_id": 42,
"household_name": "Doe household",
"donor_id": 42,
"household_relationship": "Church",
"primary_relationship": "Church",
"address": {
"line1": "10 Main Street",
"line2": "Apt 2",
"city": "Kampala",
"state": "Central",
"postal_code": "00000",
"country": "Uganda"
},
"json_fields": {},
"plan_impact_version": "issued-household-impact-version",
"plan_repairs": [
{
"plan_id": 42,
"action": "replace_action_donor",
"action_donor_id": 42,
"reason": "Household is being removed."
}
]
}
'import requests
url = "https://api.gratona.com/v1/admin/households/create-from-donor"
payload = {
"primary_contact_id": 42,
"household_name": "Doe household",
"donor_id": 42,
"household_relationship": "Church",
"primary_relationship": "Church",
"address": {
"line1": "10 Main Street",
"line2": "Apt 2",
"city": "Kampala",
"state": "Central",
"postal_code": "00000",
"country": "Uganda"
},
"json_fields": {},
"plan_impact_version": "issued-household-impact-version",
"plan_repairs": [
{
"plan_id": 42,
"action": "replace_action_donor",
"action_donor_id": 42,
"reason": "Household is being removed."
}
]
}
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({
primary_contact_id: 42,
household_name: 'Doe household',
donor_id: 42,
household_relationship: 'Church',
primary_relationship: 'Church',
address: {
line1: '10 Main Street',
line2: 'Apt 2',
city: 'Kampala',
state: 'Central',
postal_code: '00000',
country: 'Uganda'
},
json_fields: {},
plan_impact_version: 'issued-household-impact-version',
plan_repairs: [
{
plan_id: 42,
action: 'replace_action_donor',
action_donor_id: 42,
reason: 'Household is being removed.'
}
]
})
};
fetch('https://api.gratona.com/v1/admin/households/create-from-donor', 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/households/create-from-donor",
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([
'primary_contact_id' => 42,
'household_name' => 'Doe household',
'donor_id' => 42,
'household_relationship' => 'Church',
'primary_relationship' => 'Church',
'address' => [
'line1' => '10 Main Street',
'line2' => 'Apt 2',
'city' => 'Kampala',
'state' => 'Central',
'postal_code' => '00000',
'country' => 'Uganda'
],
'json_fields' => [
],
'plan_impact_version' => 'issued-household-impact-version',
'plan_repairs' => [
[
'plan_id' => 42,
'action' => 'replace_action_donor',
'action_donor_id' => 42,
'reason' => 'Household is being removed.'
]
]
]),
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/households/create-from-donor"
payload := strings.NewReader("{\n \"primary_contact_id\": 42,\n \"household_name\": \"Doe household\",\n \"donor_id\": 42,\n \"household_relationship\": \"Church\",\n \"primary_relationship\": \"Church\",\n \"address\": {\n \"line1\": \"10 Main Street\",\n \"line2\": \"Apt 2\",\n \"city\": \"Kampala\",\n \"state\": \"Central\",\n \"postal_code\": \"00000\",\n \"country\": \"Uganda\"\n },\n \"json_fields\": {},\n \"plan_impact_version\": \"issued-household-impact-version\",\n \"plan_repairs\": [\n {\n \"plan_id\": 42,\n \"action\": \"replace_action_donor\",\n \"action_donor_id\": 42,\n \"reason\": \"Household is being removed.\"\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/households/create-from-donor")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"primary_contact_id\": 42,\n \"household_name\": \"Doe household\",\n \"donor_id\": 42,\n \"household_relationship\": \"Church\",\n \"primary_relationship\": \"Church\",\n \"address\": {\n \"line1\": \"10 Main Street\",\n \"line2\": \"Apt 2\",\n \"city\": \"Kampala\",\n \"state\": \"Central\",\n \"postal_code\": \"00000\",\n \"country\": \"Uganda\"\n },\n \"json_fields\": {},\n \"plan_impact_version\": \"issued-household-impact-version\",\n \"plan_repairs\": [\n {\n \"plan_id\": 42,\n \"action\": \"replace_action_donor\",\n \"action_donor_id\": 42,\n \"reason\": \"Household is being removed.\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gratona.com/v1/admin/households/create-from-donor")
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 \"primary_contact_id\": 42,\n \"household_name\": \"Doe household\",\n \"donor_id\": 42,\n \"household_relationship\": \"Church\",\n \"primary_relationship\": \"Church\",\n \"address\": {\n \"line1\": \"10 Main Street\",\n \"line2\": \"Apt 2\",\n \"city\": \"Kampala\",\n \"state\": \"Central\",\n \"postal_code\": \"00000\",\n \"country\": \"Uganda\"\n },\n \"json_fields\": {},\n \"plan_impact_version\": \"issued-household-impact-version\",\n \"plan_repairs\": [\n {\n \"plan_id\": 42,\n \"action\": \"replace_action_donor\",\n \"action_donor_id\": 42,\n \"reason\": \"Household is being removed.\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"message": "Household created successfully with related donor",
"household": {
"id": 42,
"name": "Doe household",
"donor_ids": [
42
],
"primary_contact": {
"id": 42,
"name": "Jane Doe"
},
"related_donor": {
"id": 42,
"name": "Jane Doe",
"relationship": "Example"
}
}
}{
"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"
}{
"status": "error",
"code": "PLAN_IMPACT_CONFIRMATION_REQUIRED",
"message": "Review household plan impact before saving.",
"data": {
"material_impact": false,
"affected_plans": [
{
"id": 42,
"subject": {
"type": "donor",
"id": 42
},
"stage": "qualifying",
"status": "draft",
"period": {
"start": "2026-10-20",
"end": "2026-10-20"
},
"version": 2,
"action_donor_id": 42,
"scope_version": 2
}
],
"group_plans": [
"<string>"
],
"transfer_candidates": [
"<string>"
],
"scope_changes": [
{
"plan_id": 42,
"next_members": [
{
"member_type": "donor",
"member_id": 42,
"scope_role": "core"
}
],
"eligible_action_donor_ids": [
42
],
"invalid_open_move_ids": [
42
]
}
],
"eligible_action_donor_ids": [
42
],
"collisions": [
{
"plan_id": 42,
"conflicting_plan": {}
}
],
"authority_changes": [
"<string>"
],
"required_repairs": [
{
"plan_id": 42,
"choices": [
"replace_action_donor"
],
"eligible_action_donor_ids": [
42
],
"recommended_action_donor_id": 42
}
],
"proposed_member_donor_ids": [
42
],
"primary_contact_id": 42,
"plan_repairs": [
{
"plan_id": 42
}
],
"command": "household_membership",
"expires_at": "2026-10-20T12:00:00Z",
"impact_version": "issued-household-impact-version",
"conflicts": [
{
"plan_id": 42,
"conflicting_plan": {}
}
]
}
}{
"errors": {},
"status": "error",
"message": "The given data was invalid."
}{
"success": false,
"message": "Failed to update household",
"error": "Unable to complete household change."
}