API reference

Access token

Exchanges your API keys for a short-lived Bearer token. Every payment call — starting with initiate payment — is authenticated with this token, never with your keys directly.

POST{{base_url}}/authentication/token

No Authorization header on this call — the JSON body carries the credentials. Both keys come from the merchant panel.

Request body

client_idstringrequiredYour Client/Primary key from the merchant panel. Safe to keep in server-side config, but never expose it in front-end code.
secret_idstringrequiredYour Secret key. Treat it like a password — a wrong or revoked value returns 400 · Invalid secret ID.

Token lifetime

The response returns access_token (a long opaque string, ~350 characters) and expire_time: 600 — the token is valid for 600 seconds from issue.

  • Request a fresh token per checkout session — the two calls (token, then payment/create) comfortably fit inside the window.
  • Don’t cache tokens beyond expire_time. A stale token makes payment calls fail with 403 · Requested with invalid token! — see error handling.
  • Whether the token operates in sandbox or production follows the mode of the key pair that issued it, not the URL — see environments & base URL.
Keep keys server-side
  • Only ever call this endpoint from your backend. Shipping secret_id to a browser or mobile app exposes your merchant account.
  • The keys in the example are the public demo account’s — swap in your own from the merchant panel.
Request PHP · Guzzle
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST',
  '{{base_url}}/authentication/token', [
  'json' => [
    'client_id' => 'tRCDXCuztQzRYThPwlh1KXAYm4bG3rwWjbxM2R63kTefrGD2B9jNn6JnarDf7ycxdzfnaroxcyr5cnduY6AqpulRSebwHwRmGerA',
    'secret_id' => 'oZouVmqHCbyg6ad7iMnrwq3d8wy9Kr4bo6VpQnsX6zAOoEs4oxHPjttpun36JhGxDl7AUMz3ShUqVyPmxh4oPk3TQmDF7YvHN5M3',
  ],
  'headers' => [
    'accept'       => 'application/json',
    'content-type' => 'application/json',
  ],
]);

echo $response->getBody();
Response 200 OK
{
  "message": {
    "code": 200,
    "success": ["SUCCESS"]
  },
  "data": {
    "access_token": "nyXPO8Re5SXP1c5gMqHbW6DQ5BfQdbYGpuWVjEQAP76SUT7YfdngoFzDGSNHTvmzq8AjPRrCyzxzukrJvOlSSwtAPAqjvAQJdse4YOnlHasD3vg6EYg6qyKxSiHeXBoRluD2NbZzxN3sAYVqd9q1XCAl7oaW3BbJl2ktEQWBUuNYMZPQaDyNEGwxoY389TCNJvxVcroveYxPJkYANvnaxOy16aE9Qp6EBClSjvK17WR3cJupTXlUhgw9ddpv1gDSlbDJvzKutrQX7XJqwk1GW1Dm6aK4PTn1D4mvMVqiOqQKigTzcEi2KPQnkoM86ONw3X8SxttFOfesdSwxKJMXuQpdnFHOjo",
    "expire_time": 600
  },
  "type": "success"
}
Response 400 · invalid secret
{
  "message": {
    "code": 400,
    "error": ["Invalid secret ID"]
  },
  "data": [],
  "type": "error"
}