Errors
Error codes for both surfaces, in one place.
OAuth2 errors (sign-in)
Returned on the authorization callback (as error + error_description) or from the token endpoint:
| Error | HTTP | Cause | What to do |
|---|---|---|---|
invalid_client | 401 | Unknown client_id | Verify your client credentials, and that the app is approved (see below) |
invalid_grant | 400 | Code expired or already used | Restart the flow |
invalid_redirect_uri | 400 | redirect_uri not registered | Register the exact URI |
invalid_scope | 400 | A requested scope isn't allowed | Request only approved scopes |
invalid_request | 400 | Missing PKCE parameters | Include code_challenge / code_verifier |
account_setup_required | — | User hasn't finished Ppoppo registration | Prompt them to complete it |
External API errors (gRPC status codes)
The External API returns errors as gRPC Status; details are in the message:
| Status (code) | Cause | What to do |
|---|---|---|
UNAUTHENTICATED (16) | Token missing, expired, or invalid | Re-fetch the client_credentials token; check the authorization: Bearer metadata |
PERMISSION_DENIED (7) | App suspended, IP not allow-listed, or missing scope | Verify app status, allowed IPs, and scopes |
NOT_FOUND (5) | Template, recipient, or send request not found | Check the id belongs to your app |
INVALID_ARGUMENT (3) | Bad parameters (e.g. malformed ppnum) | Read the message for the offending field |
RESOURCE_EXHAUSTED (8) | Rate limit or monthly quota exceeded | Back off using retry-after-ms; consider a higher plan |
FAILED_PRECONDITION (9) | Template inactive, or app not approved | Ensure preconditions are met |
ALREADY_EXISTS (6) | Template name already taken within your app | Use a different name |
UNAVAILABLE (14) | Service temporarily unavailable | Retry with exponential backoff |
INTERNAL (13) | Server-side error | Retry; contact support if it persists |
Reading a recovery ladder
Error messages shift as upstream issues clear. A failing send might report "Invalid token" → "Template not found" → success — each step is progress, not regression. Treat intermediate errors as rungs on a ladder rather than restarting from scratch.
"invalid_client" on the login button
If the login redirect fails with invalid_client, your app isn't registered or approved yet. This is resolved on the Ppoppo side — either a Ppoppo admin registers your app, or you self-register and wait for approval. Once approved, the login button redirects to the Ppoppo sign-in page normally.