Skip to main content

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'" }
StatusWhen
400Bad input — invalid format, missing ids, too many ids, invalid decision, etc.
401Missing/invalid API key or Firebase token.
403Request didn't come through the official endpoint (Cloudflare gate).
404Institution not found.
500Unexpected 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:

  1. Call without a cursor.
  2. If has_next is true, the response includes a cursor string.
  3. Pass it back as ?cursor=… to fetch the next page.
  4. Stop when has_next is false (no cursor is 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.