Embed a Call Widget
This guide shows how to add AwajDigital calling to your own website.
Your agents stay logged in on your site. When they click Call, a phone popup opens so they can dial, answer, mute, and hang up. You keep your AwajDigital API token on your server. The browser only talks to your site; your API token never goes to the page.
You need:
- An API token from the dashboard (Profile → API Tokens)
- Call center enabled on your account
- At least one agent — store that agent’s numeric id on your user (List Agents returns those ids)
- Every production hostname added under Profile → Call SDK. Pages must be HTTPS.
shop.example.commatches that host only;*.shop.example.commatches its subdomains (not the apex). Up to 25 domains. An empty list rejects every origin.
Give each of your users one agent. One agent can be used in only one browser at a time.
For local http://localhost development, turn on localhost test mode on the same Call SDK page (1 or 3 days). While it is on, any origin can connect, including http://localhost. It turns itself off when the window expires. localhost is not a valid allowlist entry.
1. Add a token route on your server
Section titled “1. Add a token route on your server”When the phone needs to connect, it POSTs to your site (cookies / login still apply). Your route calls us with the API token, then returns the JSON unchanged.
POST https://api.awajdigital.com/api/sdk/token
Send { "agent_id": 42 } with Authorization: Bearer your_api_token.
You get { "token": "avt_…", "session_url": "https://api.awajdigital.com/api/sdk/session", … }.
use Illuminate\Http\Request;use Illuminate\Support\Facades\Http;use Illuminate\Support\Facades\Route;
Route::post('/amarvoice-token', function (Request $request) { $response = Http::withToken(config('services.awajdigital.token')) ->acceptJson() ->post('https://api.awajdigital.com/api/sdk/token', [ 'agent_id' => $request->user()->awaj_agent_id, ]);
return response()->json($response->json(), $response->status());})->middleware('auth');Put this in routes/api.php so the browser calls /api/amarvoice-token. (auth can be auth:sanctum if that is what you use.)
In .env:
AWAJDIGITAL_API_TOKEN=your_api_token_hereIn config/services.php:
'awajdigital' => [ 'token' => env('AWAJDIGITAL_API_TOKEN'),],awaj_agent_id is your column. Map each logged-in user to one AwajDigital agent id.
app.post('/api/amarvoice-token', requireAuth, async (req, res) => { const response = await fetch('https://api.awajdigital.com/api/sdk/token', { method: 'POST', headers: { Authorization: `Bearer ${process.env.AWAJDIGITAL_API_TOKEN}`, Accept: 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify({ agent_id: req.user.awajAgentId }), }); res.status(response.status).json(await response.json());});$ch = curl_init('https://api.awajdigital.com/api/sdk/token');curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('AWAJDIGITAL_API_TOKEN'), 'Accept: application/json', 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode([ 'agent_id' => $currentUser->awaj_agent_id, ]),]);$body = curl_exec($ch);$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);curl_close($ch);
http_response_code($code);header('Content-Type: application/json');echo $body;import osimport requestsfrom flask import jsonify
@app.post('/api/amarvoice-token')@login_requireddef amarvoice_token(): response = requests.post( 'https://api.awajdigital.com/api/sdk/token', headers={ 'Authorization': f"Bearer {os.environ['AWAJDIGITAL_API_TOKEN']}", 'Accept': 'application/json', }, json={'agent_id': current_user.awaj_agent_id}, timeout=10, ) return jsonify(response.json()), response.status_codeIf this fails: 401 bad API token, 403 call center off or agent not active, 404 that agent_id is not yours.
2. Put the widget on the page
Section titled “2. Put the widget on the page”There are two ways to start a call from your page. Most sites use the first. Both are covered in Browser Widget.
Let the SDK listen to your buttons.
<button type="button" data-call="01712345678">Call customer</button><button type="button" id="open-phone">Open phone</button>
<script src="https://dashboard.awajdigital.com/sdk/amarvoice-call.js"></script><script> const phone = new AmarVoiceCall({ tokenUrl: '/api/amarvoice-token', });
phone.mount('[data-call], #open-phone');</script>Against that HTML:
[data-call]is the “Call customer” button.data-callis special: its value is the number. Clicking it opens the phone and starts a call to01712345678.#open-phoneis the “Open phone” button. Any other element you pass tomountonly opens the keypad, so the agent can type a number.- Incoming calls open the popup too.
- The browser will ask for the microphone. That is required.
Call from your own JavaScript when the number is in your code, not on the button.
<button type="button" id="call-selected">Call selected customer</button>
<script src="https://dashboard.awajdigital.com/sdk/amarvoice-call.js"></script><script> const phone = new AmarVoiceCall({ tokenUrl: '/api/amarvoice-token', });
phone.mount();
// selectedCustomer.phone is your data — not a data-call attribute document.getElementById('call-selected').addEventListener('click', () => { phone.call(selectedCustomer.phone); });</script>mount() with no selector still puts the popup on the page, but does not wire any buttons. Your click handler reads the number from your own data; phone.call opens the popup and starts that call. Use the same phone.call(number) from a table row, a search result, or any other function. See Browser Widget for opening the keypad only, mixing both styles, and other patterns.
3. Stop the session when they log out
Section titled “3. Stop the session when they log out”DELETE https://api.awajdigital.com/api/sdk/session with { "agent_id": 42 } and your API token.
Http::withToken(config('services.awajdigital.token')) ->acceptJson() ->delete('https://api.awajdigital.com/api/sdk/session', [ 'agent_id' => $request->user()->awaj_agent_id, ]);Call this in your logout action.
await fetch('https://api.awajdigital.com/api/sdk/session', { method: 'DELETE', headers: { Authorization: `Bearer ${process.env.AWAJDIGITAL_API_TOKEN}`, Accept: 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify({ agent_id: req.user.awajAgentId }),});$ch = curl_init('https://api.awajdigital.com/api/sdk/session');curl_setopt_array($ch, [ CURLOPT_CUSTOMREQUEST => 'DELETE', CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('AWAJDIGITAL_API_TOKEN'), 'Accept: application/json', 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode([ 'agent_id' => $currentUser->awaj_agent_id, ]),]);curl_exec($ch);curl_close($ch);requests.delete( 'https://api.awajdigital.com/api/sdk/session', headers={ 'Authorization': f"Bearer {os.environ['AWAJDIGITAL_API_TOKEN']}", 'Accept': 'application/json', }, json={'agent_id': current_user.awaj_agent_id}, timeout=10,)A call that is already connected is not cut off. The next page load starts from step 2 again.
