REST conventions
Base URL and versioning
https://api.ministrium.com/v1/<resource>Version is in the URL (/v1/). Breaking changes bump to v2. Additive changes (new fields, new endpoints) are NOT breaking — clients must ignore unknown fields.
Resources and verbs
GET /v1/members List
POST /v1/members Create
GET /v1/members/{id} Get
PATCH /v1/members/{id} Partial update
PUT /v1/members/{id} Replace (rare, prefer PATCH)
DELETE /v1/members/{id} Delete (soft delete)Sub-resources:
GET /v1/members/{id}/attendance
GET /v1/members/{id}/donations
GET /v1/groups/{id}/membersFormat
Everything is JSON UTF-8. Standard headers:
Content-Type: application/json; charset=utf-8
Accept: application/json
Accept-Language: en-USAccept-Language affects error messages and fields like gender_label, status_label. Default: es.
IDs
IDs are readable prefixed UUIDs:
mem_8c4b2e1a3d4f5b6c7d8e9f0a1b2c3d4e Member
don_4f5g6h7i8j9k0l1m2n3o4p5q6r7s8t9u Donation
evt_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 Event
grp_z9y8x7w6v5u4t3s2r1q0p9o8n7m6l5 Cell groupThe prefix tells you the type without checking the endpoint.
Cursor pagination
Lists return a cursor:
{
"data": [{...}, {...}],
"next_cursor": "eyJvZmZzZXQiOjEwMH0=",
"total": 4327
}For the next page:
GET /v1/members?cursor=eyJvZmZzZXQiOjEwMH0=&limit=100Max limit: 250. Default: 50.
When `next_cursor` is `null`, you've reached the end.Filters
GET /v1/members?campus=downtown&active=true&created_after=2026-01-01Query-string operators for numeric/date fields:
?age[gte]=18&age[lt]=35
?created_at[gte]=2026-01-01T00:00:00ZSorting
?sort=created_at Ascending
?sort=-created_at Descending
?sort=last_name,first_name MultipleIdempotency
For POST requests that create resources, send Idempotency-Key (UUID v4):
curl -X POST /v1/donations \
-H "Idempotency-Key: 6ba7b810-9dad-11d1-80b4-00c04fd430c8" \
...Retrying with the same key within 24 h returns the original response without re-executing.
Dates and times
ISO 8601 with timezone. All responses in UTC; send in UTC too:
2026-04-26T14:30:00Z
2026-04-26T08:30:00-06:00 ← also valid, normalized to UTC in responseDate only: 2026-04-26.
Currencies
Amounts as integers in the smallest unit (cents):
{ "amount": 5000, "currency": "MXN" } // = $50.00 MXN
{ "amount": 12500, "currency": "USD" } // = $125.00 USDThis avoids float rounding errors.
CORS
The church’s own domains can make direct browser requests if allowlisted (Settings → API → CORS). By default the API does not accept browser requests from unknown origins.
ETag and cache
GET responses include ETag. Use If-None-Match to skip transferring unchanged data:
GET /v1/members/mem_123 -H "If-None-Match: \"abc123\""
→ 304 Not Modified