Quick Start
This guide shows you how to integrate Bank Hub into your app in a few simple steps – from creating tokens and linking them to embedding webview iframes and receiving balance change notifications.
- Obtain an
access_tokenfrom the/v1/tokenAPI - Use the
access_tokento create a link token - Embed the
hosted_link_urlinto an iframe on your website
Make sure you have:
client_idandclient_secretprovided by SePaycompany_xid(UUID of the company created in the Bank Hub system) – Create Company API- A backend server to call APIs (do not call APIs from the client-side for security reasons)
Step 1: Get Access Token
- First, you need to obtain an
access_tokento authenticate subsequent API calls. This API uses Basic Authentication withclient_idandclient_secret.
DO NOT call this API from the client-side (browser or mobile app). This API requires client_secret, which must be strictly protected on the server. Only call this API from your backend server.
- API Endpoint
https://bankhub-api-sandbox.sepay.vn/v1/tokenAuthorization: Basic {base64(client_id:client_secret)}
Content-Type: application/x-www-form-urlencoded- Code examples
<?php// File: app/Services/BankHubService.phpnamespace App\Services;use Illuminate\Support\Facades\Http;class BankHubService{private $clientId;private $clientSecret;private $baseUrl;public function __construct(){$this->clientId = config('bankhub.client_id');$this->clientSecret = config('bankhub.client_secret');$this->baseUrl = config('bankhub.base_url', 'https://bankhub-api-sandbox.sepay.vn');}/*** Get access token from Bank Hub*/public function getAccessToken(): ?string{$response = Http::withBasicAuth($this->clientId, $this->clientSecret)->post($this->baseUrl . '/v1/token');if ($response->successful()) {$data = $response->json();return $data['access_token'] ?? null;}throw new \Exception('Failed to get access token: ' . $response->body());}}
- Response
{
"code": 201,
"access_token": "36483db493b10304eb3abc143b3593fa1473eb9b",
"ttl": 60000
}- Store the
access_tokenin cache (Redis, Memcached) or session - The token has a limited lifetime (
ttl), so implement automatic refresh logic - When receiving a
401 Unauthorizederror, automatically request a new token
Step 2: Create Link Token
After obtaining the access_token, use it to create a link token. The link token provides a hosted_link_url, which will be embedded into an iframe.
- API Endpoint
https://bankhub-api-sandbox.sepay.vn/v1/link-token/createAuthorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json- Code examples
<?php// File: app/Services/BankHubService.php (continued)namespace App\Services;use Illuminate\Support\Facades\Http;class BankHubService{// ... (getAccessToken code above)/*** Create link token to link bank account*/public function createLinkToken(string $companyXid,string $purpose = 'LINK_BANK_ACCOUNT',?string $redirectUri = null): array {$accessToken = $this->getAccessToken();$payload = ['company_xid' => $companyXid,'purpose' => $purpose,];if ($redirectUri) {$payload['completion_redirect_uri'] = $redirectUri;}$response = Http::withToken($accessToken)->post($this->baseUrl . '/v1/link-token/create', $payload);if ($response->successful()) {return $response->json();}throw new \Exception('Failed to create link token: ' . $response->body());}}// Usage in Controller:// File: app/Http/Controllers/BankHubController.phpnamespace App\Http\Controllers;use App\Services\BankHubService;use Illuminate\Http\Request;class BankHubController extends Controller{private $bankHub;public function __construct(BankHubService $bankHub){$this->bankHub = $bankHub;}public function getLinkUrl(Request $request){$companyXid = $request->user()->company_xid; // From logged in user$redirectUri = route('bankhub.callback'); // Your callback URL$result = $this->bankHub->createLinkToken($companyXid,'LINK_BANK_ACCOUNT',$redirectUri);return response()->json(['hosted_link_url' => $result['hosted_link_url'],'expires_at' => $result['expires_at']]);}}
The code examples above demonstrate creating a link token for the bank account linking flow. If you need to create an unlink flow, set purpose to UNLINK_BANK_ACCOUNT and provide bank_account_xid.
- Response
{
"xid": "850e8400-e29b-41d4-a716-446655440000",
"hosted_link_url": "https://bankhub.sepay.vn/link/850e8400-e29b-41d4-a716-446655440000",
"link_token": "950e8400-e29b-41d4-a716-446655440000",
"expires_at": "2024-01-17 10:30:00"
}- Full details of the link token API: Create Link Token API
Step 3: Embed Iframe into Website
After receiving the hosted_link_url from Step 2, you can embed it into your website using an iframe.
<!DOCTYPE html><html><head><title>Link Bank Account</title><style>.bankhub-container {width: 100%;max-width: 800px;margin: 0 auto;padding: 20px;}.bankhub-iframe {width: 100%;height: 600px;border: 1px solid #e5e7eb;border-radius: 8px;box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);}</style></head><body><div class="bankhub-container"><h1>Link Bank Account</h1><iframeid="bankhub-iframe"class="bankhub-iframe"src=""frameborder="0"allow="clipboard-write"></iframe></div><script>// Call backend API to get hosted_link_urlasync function loadBankHubLink() {try {const response = await fetch('/api/bankhub/get-link-url', {method: 'POST',headers: {'Content-Type': 'application/json','Authorization': `Bearer ${userToken}`}});const data = await response.json();document.getElementById('bankhub-iframe').src = data.hosted_link_url;} catch (error) {console.error('Error loading Bank Hub link:', error);alert('Unable to load bank linking interface. Please try again.');}}loadBankHubLink();// Listen to events from iframe (postMessage)window.addEventListener('message', function(event) {if (event.origin !== 'https://bankhub.sepay.vn') return;const { event: eventType, metadata, timestamp } = event.data;switch(eventType) {case 'FINISHED_BANK_ACCOUNT_LINK':console.log('Account linked:', metadata);alert(`Linked successfully: ${metadata.account_number}`);window.location.href = '/dashboard';break;case 'FINISHED_BANK_ACCOUNT_UNLINK':console.log('Account unlinked');alert('Unlinked successfully!');window.location.href = '/dashboard';break;case 'BANKHUB_CLOSE_LINK':console.log('User closed linking flow');break;case 'BANKHUB_TOKEN_EXPIRED':console.warn('Token expired');alert('Session expired. Please try again.');break;case 'BANKHUB_SESSION_EXPIRED':console.warn('Session expired');alert('Session expired. Please try again.');break;}});</script></body></html>
If you provided completion_redirect_uri when creating the link token, users will be redirected to that URL after completion.
PostMessage Events
The iframe sends events via window.postMessage in the following format:
{
"event": "FINISHED_BANK_ACCOUNT_LINK | FINISHED_BANK_ACCOUNT_UNLINK | BANKHUB_CLOSE_LINK | BANKHUB_TOKEN_EXPIRED | BANKHUB_SESSION_EXPIRED",
"metadata": {
"account_number": "string",
"account_type": "individual | enterprise"
},
"timestamp": "string"
}Event types:
The bank account has been successfully linked. Metadata contains account information.
The bank account has been successfully unlinked.
The user closes or cancels the linking flow.
The link token has expired and a new token must be created.
The session has expired and must be re-initialized.