https:// URLs where Synci sends users back after they approve. No wildcards, no trailing-slash differences. While your app is in testing, http:// is also allowed for loopback hosts (localhost, 127.0.0.1, ::1) so you can develop locally; loopback URIs must be replaced with https:// before you submit for review.code_verifier (43 to 128 characters), then derive the challenge:code_challenge = BASE64URL( SHA256( code_verifier ) )state string to protect against CSRF.GET https://api.synci.io/oauth/authorize
?response_type=code
&client_id=YOUR_CLIENT_ID
&redirect_uri=https://yourapp.com/callback
&scope=accounts:read%20transactions:read
&state=RANDOM_STATE
&code_challenge=YOUR_CODE_CHALLENGE
&code_challenge_method=S256%20) and must be a subset of the scopes your app is registered for.https://yourapp.com/callback?code=AUTH_CODE&state=RANDOM_STATEstate matches what you sent before continuing. The code is single-use and expires after about 10 minutes.?error=access_denied instead of a code.application/x-www-form-urlencoded, not JSON:{
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "eyJ0eXAiOi...",
"refresh_token": "def50200..."
}403, and accounts the user did not select return 404.| State | Who can authorize | Editing |
|---|---|---|
| Testing | You and invited testers | Changes take effect immediately |
| Pending review | No new authorizations | Locked while under review |
| Approved | Any Synci user; your app is marked verified | Changes to branding, scopes, and redirect URIs are queued for re-review before taking effect |
| Rejected | No one | Edit and resubmit; a reason is provided |
invalid_client.https://yourapp.com/callback is not the same as https://yourapp.com/callback/.| Error | Cause |
|---|---|
invalid_client | Wrong or missing client_id or client_secret, or the token request was sent as JSON instead of form-urlencoded. |
invalid_grant | The authorization code expired or was already used, the code_verifier does not match the original code_challenge, or the refresh token was already rotated or revoked. |
invalid_scope | A requested scope is not among the scopes your app is registered for. |
access_denied (on the redirect) | The user declined the authorization request. |
403 on an API call | The token lacks the required scope for that endpoint. |
404 on an account | The user did not grant your app that account. |