REST API
Read, create, and update people in your organisation programmatically. The API returns JSON and is authenticated with a personal access token you generate in the dashboard.
Authentication
Every request is scoped to a single organisation, resolved from the host you call, and authorised with a personal access token sent as a bearer token. The token carries exactly the permissions and division scope of the admin who created it.
- In the dashboard, open your account menu → API / MCP.
- Under Personal access tokens, give the token a name and click Generate token.
- Copy the token immediately — it's only shown once. Revoke it any time from the same page.
Send it in the Authorization header:
curl -H "Authorization: Bearer <token>" \
https://your-subdomain.cobberhq.com.au/api/v1/people
https://<your-subdomain>.cobberhq.com.au/api/v1 (or your custom domain).
A token only works against the organisation it was created for. Requests without a valid token return
401 Unauthorized.
Conventions
- Requests and responses are JSON. Send
Content-Type: application/jsonon writes. - Success returns
200(reads/updates) or201(create). - Validation failures return
422with{ "error": "validation_failed", "messages": [...] }. - A person you can't access returns
404(never leaks existence). - List endpoints paginate with
pageandper_page(default 100, max 200). - In curl examples, always quote URLs that include
?query params. On macOS, zsh treats bare?as a glob and fails withzsh: no matches found.
/api/v1/peopleSearch and list people you can access. Supports the same filters as the People page — e.g.
search, tags, state,
membership_status, volunteer_status,
donor_status, branch, plus sort/direction.
curl -H "Authorization: Bearer <token>" \
"https://your-subdomain.cobberhq.com.au/api/v1/people?search=smith&state=QLD&page=1"
Response
{
"total_count": 128,
"page": 1,
"per_page": 100,
"people": [
{
"id": 42,
"url": "https://your-subdomain.cobberhq.com.au/dashboard/people/42",
"name": "Jane Smith",
"email": "jane@example.com",
"mobile_phone": "+61 400 000 000",
"suburb": "Brisbane",
"state": "QLD",
"tags": "member,volunteer",
"membership_status": "Active",
"volunteer_status": "active"
}
]
}
/api/v1/people/:idFull detail for one person, including address, electorates, tags, custom fields, email preferences, all email addresses, and recent activity.
curl -H "Authorization: Bearer <token>" \
https://your-subdomain.cobberhq.com.au/api/v1/people/42
Response (abridged)
{
"id": 42,
"first_name": "Jane",
"last_name": "Smith",
"display_name": "Jane Smith",
"residential_suburb": "Brisbane",
"residential_state": "QLD",
"tags": "member,volunteer",
"custom_fields": { "party_membership": "Member" },
"email_preferences": { "newsletters": true, "events": false },
"volunteer_status": "active",
"membership_status": "Active",
"emails": [
{ "id": 55, "email": "jane@example.com", "primary": true, "unsubscribed": false, "bounced": false }
],
"recent_actions": [
{ "type": "donation_made", "at": "2026-02-01T03:12:00Z", "details": { "amount": "50.0" } }
]
}
/api/v1/peopleCreate a person. Provide email to set their primary email address. You can
set contact fields, tags, volunteer_status,
custom_fields, and email_preferences in the same call.
curl -X POST \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
https://your-subdomain.cobberhq.com.au/api/v1/people \
-d '{
"first_name": "Jane",
"last_name": "Smith",
"email": "jane@example.com",
"tags": "member,volunteer",
"custom_fields": { "party_membership": "Member" },
"email_preferences": { "newsletters": true, "events": false }
}'
Returns 201 with the created person in the same shape as Get a person.
/api/v1/people/:idUpdate a person. Only the fields you include change. Notable fields:
email_preferences— an object ofcategory => booleanfor your organisation's email categories. When provided, the keys you send are merged into the person's existing preferences (other categories are kept). Omit it to leave preferences untouched.unsubscribe_all_emails—trueunsubscribes every email address on the record.custom_fields— when provided, the keys you send are merged into the person's existing custom fields (other keys are kept). Omit it to leave custom fields untouched. Only keys that have been set appear on a person'scustom_fieldsin responses — use Custom field definitions to discover valid keys.volunteer_status— one ofinterested,active,inactive, orcore_team.emails— array of{ id?, email, primary?, remove? }to add/update/remove addresses.
curl -X PATCH \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
https://your-subdomain.cobberhq.com.au/api/v1/people/42 \
-d '{
"tags": "member,volunteer,lapsed",
"email_preferences": { "newsletters": false },
"unsubscribe_all_emails": true
}'
Returns 200 with the updated person.
/api/v1/custom_fieldsLists your organisation's person custom field definitions — the valid field_key
values, labels, types, and select options. Use this to discover which custom fields exist before reading or
writing people. A person's custom_fields object in GET responses only includes keys
that have been set at least once on that record, so older people won't show fields added later until a value is
written.
curl -H "Authorization: Bearer <token>" \
https://your-subdomain.cobberhq.com.au/api/v1/custom_fields
Response
{
"groups": [
{
"name": "Custom Fields",
"description": null,
"fields": [
{
"field_key": "party_membership",
"label": "Party Membership",
"field_type": "select",
"required": false,
"options": ["None", "Member"]
}
]
}
]
}
/api/v1/paymentsRecord a payment captured outside the online (Stripe) flow — a cash or cheque donation, EFTPOS at a
stall, or a merchandise sale. It is stored as a succeeded payment and appears in the Finances report and on the
person's profile, just like an online payment. Requires the finances.read permission.
Fields:
person_id— required; the person the payment is attributed to (must be one you can access).amount— required; a positive decimal.payment_method—cash,cheque,bank_transfer, orother.payment_type—donation(default) orother(e.g. merch).received_on— optional date the money was received (defaults to today); the payment is dated to this.description,reason,tax_deductible— optional.
curl -X POST \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
https://your-subdomain.cobberhq.com.au/api/v1/payments \
-d '{
"person_id": 42,
"amount": "50.00",
"payment_method": "cash",
"payment_type": "donation",
"received_on": "2026-02-01",
"description": "Cash donation at the branch stall"
}'
Response
{
"id": 918,
"person_id": 42,
"amount": "50.0",
"payment_type": "donation",
"payment_method": "cash",
"status": "succeeded",
"processed_at": "2026-02-01T00:00:00Z",
"metadata": { "manual_entry": true, "created_by_admin": "you@example.com" }
}
MCP (AI assistants)
The same data is available to AI assistants over the Model Context Protocol. Point an MCP client
(Claude, ChatGPT, etc.) at https://<your-subdomain>.cobberhq.com.au/mcp and it
will walk you through signing in. See API / MCP in the dashboard for
client-by-client setup.