Authentication Flow
Learn the details of the OAuth2 authentication flow and how to implement it in your application.
Authentication Flow Overview
SePay implements OAuth2 using the Authorization Code flow, one of the most common and secure OAuth2 flows. This flow is suitable for most web and server-side applications.

OAuth2 SePay Flowchart The OAuth2 authentication flow in SePay includes the following steps:
- Step 1 The application requests authorization from the user by redirecting to SePay’s authorization URL
- Step 2 The user signs in to SePay and agrees to grant permissions to the application
- Step 3 SePay redirects back to the application’s redirect URI with an authorization code
- Step 4 The application exchanges the authorization code for an access token from SePay
- Step 5 The application uses the access token to call SePay’s APIs
Step 1: Request authorization
- To begin the authentication process, redirect the user to SePay’s authorization URL:
https://my.sepay.vn/oauth/authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&scope=bank-account:read transaction:read&state=RANDOM_STATE_VALUE- Explanation of URL parameters
| Name | Type | Required | Description |
|---|---|---|---|
response_type | string | Required | Must be code for the Authorization Code flow |
client_id | string | Required | Your application’s Client ID, obtained when registering the app |
redirect_uri | string | Required | The URL that receives the authorization code; must match the registered URL |
scope | string | Required | Requested access scopes, separated by spaces |
state | string | Required | Random value to prevent CSRF attacks; returned unchanged; optional (defaults to all registered scopes) |
The state parameter should be used to protect against CSRF attacks. Generate a random value, store it in the session, and verify it when receiving the callback.
Step 2: User grants permission
After being redirected to the authorization URL, the user will see the SePay login screen (if not already logged in) and then the consent screen:

OAuth2 SePay This screen shows:
- The name of the application requesting access
- The permissions the application is requesting
- Buttons to approve or deny access
Step 3: Receive the authorization code
- After the user grants permission, SePay redirects to your
redirect_uriwith the authorization code:
https://your-app.com/callback?code=AUTHORIZATION_CODE&state=RANDOM_STATE_VALUE- Your application should:
- Verify the
stateparameter matches the value previously sent - Extract the authorization code from the
codeparameter
- Verify the
The authorization code is valid only for a short period (usually 5 minutes) and can be used once. Exchange it for an access token immediately after receiving it.
Step 4: Exchange the authorization code for an access token
- After receiving the authorization code, exchange it for an access token by sending a POST request to SePay’s token endpoint:
https://my.sepay.vn/oauth/token-H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=authorization_code" \ -d "code=AUTHORIZATION_CODE" \ -d "redirect_uri=YOUR_REDIRECT_URI" \ -d "client_id=YOUR_CLIENT_ID" \ -d "client_secret=YOUR_CLIENT_SECRET"
- Parameter explanation
Name Type Required Description grant_typestring Required Must be authorization_codecodestring Required Authorization code received from the previous stepredirect_uristring Required Redirect URL identical to the one used in Step 1client_idstring Required Your application’s Client IDclient_secretstring Required Your application’s Client Secret
This token exchange request must be performed on the server side. Never perform it on the client side because it requires using the client_secret.
Step 5: Use the access token to call APIs
After receiving the access token, you can use it to call SePay APIs by adding it to the
Authorizationheader:GET[https://my.sepay.vn/api/v1/bank-accounts](https://my.sepay.vn/api/v1/bank-accounts)-H Authorization: Bearer ACCESS_TOKEN
Below is a cURL example:
cURLcurl -H 'Authorization: Bearer ACCESS_TOKEN' [https://my.sepay.vn/api/v1/bank-accounts](https://my.sepay.vn/api/v1/bank-accounts)
Step 6: Refresh the access token
- The access token is only valid for a limited period (typically 1 hour). When the access token expires, you need to use the refresh token to obtain a new token without requiring the user to re-authenticate:
[https://my.sepay.vn/oauth/token](https://my.sepay.vn/oauth/token)-H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=refresh_token" \ -d "refresh_token=REFRESH_TOKEN" \ -d "client_id=YOUR_CLIENT_ID" \ -d "client_secret=YOUR_CLIENT_SECRET"
- Parameter explanation
Name Type Required Description grant_typestring Required Must be refresh_tokenrefresh_tokenstring Required Refresh token received when obtaining the access tokenclient_idstring Required Your application’s Client IDclient_secretstring Required Your application’s Client Secret
Store the refresh token securely and implement automatic token refresh when the access token is close to expiring or when the API returns 401 Unauthorized.
Error handling
- When an error occurs during authentication, SePay will return a corresponding error code. Common errors include:
| Error Code | Description | Solution |
|---|---|---|
invalid_request | The request is missing a required parameter or contains an invalid parameter | Re-check all request parameters |
invalid_client | Client authentication failed | Verify client_id and client_secret |
invalid_grant | Authorization code or refresh token is invalid or expired | Ask the user to re-authenticate or verify the refresh token |
unauthorized_client | The client is not allowed to request an authorization code | Check your application configuration |
access_denied | The user denied the request | Inform the user that access must be granted to use the application |
unsupported_grant_type | The server does not support the requested grant type | Check the grant_type parameter |
invalid_scope | The requested scope is invalid, unrecognized, or exceeds the registered scopes | Verify the requested scopes |
- Error responses are formatted as:
{
"error": "invalid_grant",
"error_description": "Authorization code expired"
}Next Steps
- After understanding the OAuth2 authentication flow, you are ready to implement it in your application. Next, learn how to use the Access Token with SePay’s APIs.