Skip to content

Developer guide

This page is for whoever builds your church’s own website or automations. HolyCRM offers two ways to connect:

  • Public data feeds: your website reads your events, small groups, service times and ministries from HolyCRM, always up to date.
  • Webhooks: HolyCRM sends announcements and what happens in your church (new visitors, members, prayer requests, registrations, serving answers) to an address of yours.

Both are part of the Pro plan, and only an Administrator can turn them on, in Settings → Integrations.

In Integrations → Public data feeds, an Administrator ticks the feeds to share and clicks Save. The address of each feed appears under it, with a Copy button. Untick a feed and save to stop it at once.

Each feed carries exactly what the church’s HolyCRM website shows, never more. Member records, children, notes, addresses of homes and group hosts are never included.

Every church has its own addresses, built from its HolyCRM id (the screen shows them in full):

Address What it returns
https://pb.holycrm.app/backend/api/public/feeds/<id> The church’s name and time zone, and the address of every feed that is on
…/feeds/<id>/events Upcoming events
…/feeds/<id>/groups Small groups marked “Show on the website”
…/feeds/<id>/services Weekly service times marked “Show on the website”
…/feeds/<id>/ministries Active ministries

They need no key or login, and they can be called straight from a web page on any site (cross-origin requests are allowed). Responses may be cached for 5 minutes, so a change in HolyCRM shows up on your site within a few minutes.

Every feed returns JSON with the church and a list named after the feed:

{
"church": { "name": "Grace Community Church", "timezone": "America/Chicago" },
"events": [ … ]
}

A field with nothing in it is null.

Events (events), soonest first:

Field
id The event’s id
title Name of the event
starts_at Start, in UTC: "2026-11-01 15:00:00.000Z"
location_place Where it is, as typed in the event
description The public description for the website
photo_url Full address of the website photo
registration true when visitors can sign up on the church’s HolyCRM website

It takes two optional settings: ?limit= how many events (1 to 100, default 20) and ?days= how far ahead (1 to 365 days, default 90). For example …/events?limit=5&days=30.

Small groups (groups), by name:

Field
id The group’s id
name Name of the group
description The public description for the website
meeting_day mon, tue, wed, thu, fri, sat or sun
meeting_time Time as typed, local to the church, e.g. "19:30"

Service times (services), Sunday first:

Field
title Name of the activity, e.g. “Sunday service”
weekday sun … sat
time Local time at the church, e.g. "10:00"
duration_minutes Length, when set
place Name of the location, when set

Ministries (ministries), by name:

Field
id The ministry’s id
name Name of the ministry
min_age, max_age Age range, when set (for children’s and youth ministries)
description The public description for the website
photo_url Full address of the website photo

Event start times (starts_at) are in UTC. Service and group times are wall-clock times at the church. Show both in the church’s time zone, which comes in church.timezone (for example America/Argentina/Buenos_Aires).

A feed answers 404 {"error": "not found"} when it is turned off, when the address has a wrong id, or when the church is no longer on the Pro plan. A church that comes back to Pro gets its feeds back at the same addresses.

A list of the next five events on any web page:

<ul id="events"></ul>
<script>
const FEED = "https://pb.holycrm.app/backend/api/public/feeds/YOUR_CHURCH_ID/events?limit=5";
fetch(FEED)
.then((r) => r.json())
.then(({ church, events }) => {
const list = document.getElementById("events");
for (const ev of events) {
const when = new Date(ev.starts_at.replace(" ", "T")).toLocaleString(undefined, {
timeZone: church.timezone || undefined,
weekday: "long", day: "numeric", month: "long", hour: "2-digit", minute: "2-digit",
});
const li = document.createElement("li");
li.textContent = `${ev.title} · ${when}${ev.location_place ? " · " + ev.location_place : ""}`;
list.appendChild(li);
}
});
</script>

Use textContent (not innerHTML) for anything that comes from a feed, as above.

Setting up a webhook, choosing what it receives and the ready-made formats for ntfy and Telegram are explained in Integrations. What matters to a developer:

  • Each delivery is a POST with a JSON body (or your custom format). X-HolyCRM-Event says what happened, for example visitor.created.
  • X-HolyCRM-Delivery stays the same when a delivery is retried, so you can ignore duplicates.
  • Every request is signed. X-HolyCRM-Signature is sha256= followed by the HMAC-SHA256 of <X-HolyCRM-Timestamp>.<raw body>, keyed with your webhook’s signing secret.
  • Answer with any 2xx status. Timeouts (15 seconds), 408, 429, 5xx and network errors are tried again (after 30 seconds, 2, 8 and 32 minutes, then hourly, 6 attempts in all). Any other answer, including a redirect, fails at once: redirects are never followed.

With the default format the body looks like this (data depends on the event; summary is a ready-made line in the church’s language):

{
"event": "visitor.created",
"version": 1,
"id": "k3j2h1g0f9e8d7c",
"created_at": "2026-10-08T14:00:00.000Z",
"church": { "id": "abc123def456ghi", "name": "Grace Community Church" },
"data": { "first_name": "John", "last_name": "Smith", "phone": "…", "summary": "New visitor: John Smith" }
}

Checking the signature in Node.js:

const crypto = require("crypto");
function verify(rawBody, headers, secret) {
const ts = headers["x-holycrm-timestamp"];
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; // older than 5 minutes
const expected = "sha256=" + crypto.createHmac("sha256", secret).update(ts + "." + rawBody).digest("hex");
const got = String(headers["x-holycrm-signature"] || "");
return got.length === expected.length && crypto.timingSafeEqual(Buffer.from(got), Buffer.from(expected));
}

Use the raw request body, before any JSON parsing.

There is no API with keys for reading or changing member data. If your church needs one, tell us what you’d use it for through the contact form on holycrm.app.