Responses and errors
The member app API and the platform API answer in different shapes. Both are stable; read the one for the routes you call.
Member app API: {status, message}
Routes under /api/v1/ and /api/v2/ answer the way the original MyChurch API did, because the installed apps parse exactly that. A success and a business failure both come back as HTTP 200; the boolean status tells them apart and message is text to show the member.
{
"message": "Your pledge has been recorded successfully",
"status": true
}{
"message": "You have entered the wrong pin",
"status": false
}Extra fields sit beside status and message (for example token, account, transactions). A few cases use real status codes:
| HTTP | When | Body |
|---|---|---|
| 401 | Missing or unknown member token, or a token of another church on a {church} route | {"message":"Unauthenticated","status":false} |
| 401 | Wrong or missing CHURCHES-ACCESS-KEY | {"message":"Unauthorized","status":false} |
| 404 | A uuid in the path matches nothing | {"message":"No query results for model [App\\Models\\Church] <uuid>"} |
| 404 | Unknown route, or a known path with the wrong method | {"message":"Not Found"} |
| 422 | A required field is missing or malformed | The validation shape below |
| 429 | Login, registration, OTP or PIN routes called too often | {"success":false,"error":"Too many requests. Please slow down and try again."} |
| 500 | Unexpected failure | {"message":"Server Error"} |
| 503 | The member could not be resolved because a dependency is down | {"message":"Service temporarily unavailable. Please retry.","status":false} |
{
"message": "The phone field is required.",
"errors": { "phone": ["The phone field is required."] }
}Branch on status, not on the HTTP code
status: false as a failure and show its message. Treat 401 as "log in again". Treat any other non-200 as an error and retry reads with backoff.Value formats on the member app API
- Date and time columns render as
2026-10-05 10:12:40, date columns as2026-10-05, record timestamps as2026-10-05T07:12:40.000000Z; wall-clock values are Nairobi time. - Yes/no flags render as
0or1. - Some amounts are numeric strings (
"1000.00"), some formatted ("1,500.00"), as each route always returned them. - Empty text stays
""and missing values staynull; parse both. - Records are identified by
uuid. A few payloads still carry an integeridbecause the shipped apps read it; do not build on integer ids.
Churches still on the previous system
While churches move to the new platform one by one, a member of a church that has not moved yet gets HTTP 200 with status: false and the message "Your church is still on the previous MyChurch system. Please update the app or try again later" on login and registration, and 401 on other member routes.
Platform API: {success, data, error, meta}
Routes under /v1 and /auth use real HTTP status codes and one envelope:
{
"success": true,
"data": { "uuid": "00000000-0000-4000-8000-0000000000a1", "first_name": "Jane", "other_names": "Wanjiku" }
}{
"success": true,
"data": [ { "uuid": "00000000-0000-4000-8000-0000000000a1", "first_name": "Jane" } ],
"meta": { "page": 1, "page_size": 25, "total": 1 }
}{
"success": false,
"error": "You don't have permission to do that."
}data and meta are left out when empty; error is a sentence you can show a user.
| HTTP | Meaning | When |
|---|---|---|
| 400 | Bad request | The body is not valid JSON, or a parameter has the wrong shape. |
| 401 | Unauthenticated | No token, an expired or revoked token, or wrong login credentials. |
| 402 | Plan required | The feature needs the premium plan ("this feature needs the premium plan"), or the church subscription has lapsed. |
| 403 | Forbidden | The token is valid but lacks the permission, the user or church is suspended, or the church is still on the previous MyChurch system. |
| 404 | Not found | No such record in the church you are acting on (records of other churches are never visible). |
| 409 | Conflict | The change clashes with existing data, for example a duplicate account number. |
| 422 | Validation | A field failed validation; error names the problem. Also wrong or expired one-time codes. |
| 429 | Too many requests | Rate limit hit. Wait for Retry-After seconds. |
| 500 | Server error | Our fault. Safe to retry a read; for a write, check whether it happened first. |
Lists, filters and exports are described in Pagination; limits and the Retry-After header in Rate limits.