Errors & pagination
Error shape
Errors return a JSON body with a numeric code mirroring the HTTP status:
{ "code": 400, "error": "Invalid format parameter. Must be 'json' or 'csv'" }
| Status | When |
|---|---|
400 | Bad input — invalid format, missing ids, too many ids, invalid decision, etc. |
401 | Missing/invalid API key or Firebase token. |
403 | Request didn't come through the official endpoint (Cloudflare gate). |
404 | Institution not found. |
500 | Unexpected server error. The body is always a generic "Internal server error"; details are logged server-side, never returned to the client. |
Pagination
List-style endpoints (/applications, /applications/zip) use cursor
pagination:
- Call without a
cursor. - If
has_nextistrue, the response includes acursorstring. - Pass it back as
?cursor=…to fetch the next page. - Stop when
has_nextisfalse(nocursoris returned).
cursor=""
while : ; do
resp=$(curl -s "https://api.uapply.africa/api/v1/applications?limit=50&cursor=$cursor" \
-H "Authorization: Bearer $UAPI_KEY")
echo "$resp" | jq '.data[]'
has_next=$(echo "$resp" | jq -r '.has_next')
[ "$has_next" = "true" ] || break
cursor=$(echo "$resp" | jq -r '.cursor')
done
Cursors are tied to the query that produced them — keep limit, cycle, and
date filters identical across pages.
Rate limiting
The API sits behind Cloudflare, which enforces edge rate limiting and WAF
rules. Every request is also recorded (with secrets redacted) to an internal
audit log for abuse detection. Design clients to back off on 429/5xx and
to page with a reasonable limit rather than hammering small pages.