Skip to main content

Client Management

Learn how to manage API clients, check permissions, create device-specific clients, and configure client settings.

Get Current Client Information

Retrieve information about the current API client, including permissions and configuration.

Request

GET /rest/v1/client
No Extra Parameters

This endpoint always returns information about the authenticated client making the request.

Response

{
"title": "My Backend System",
"permissions": [
"show_in_frame",
"accept_with_flash",
"use_password_grant"
],
"type": "private_client"
}
View Response Fields
FieldTypeDescription
titlestringConfigured project title
permissionsarrayArray of permission identifiers
typestringClient type: private_client, application, or app_client
infoobjectAdditional client info (if available)
credentialsobjectOnly present in registration response

Client Permissions

Available Permissions

General Permissions

PermissionDescriptionClient Types
show_in_frameCan display confirmation page in iframePrivate, App
give_trusted_user_infoUser info from client is trustedPrivate
use_password_grantCan use password OAuth grantPrivate, App

Transaction Permissions

PermissionDescriptionClient Types
accept_with_flashCan confirm with FLASH SMSPrivate, App
accept_with_pinCan confirm with PIN codePrivate, App

Data Access Permissions

PermissionDescriptionClient Types
access_statementsCan access account statementsPrivate, App
search_by_person_codeCan search users by person codePrivate

Advanced Permissions

PermissionDescriptionClient Types
client_make_bank_transfersCan initiate bank transfersPrivate
use_oauth_apiCan use OAuth endpointsAll
use_wallet_apiCan use Wallet APIAll
use_client_apiCan use Client APIAll
Checking Permissions
async function checkClientPermissions() {
const client = await api.getClient();

console.log('Client Type:', client.type);
console.log('Permissions:', client.permissions);

// Check specific permission
if (client.permissions.includes('accept_with_pin')) {
console.log('✅ Can use PIN confirmation');
}

// Check multiple permissions
const hasPaymentPermissions = [
'accept_with_pin',
'accept_with_flash'
].some(perm => client.permissions.includes(perm));

if (hasPaymentPermissions) {
console.log('✅ Can process payments');
}
}

Create New Client (Mobile Apps)

Create a new device-specific client. Only available for application type clients.

Request

POST /rest/v1/client
Content-Type: application/json
{
"type": "app_client",
"info": {
"title": "John's iPhone",
"os": "iOS 17.0",
"model": "iPhone 15 Pro",
"device_id": "A1B2C3D4E5F6",
"imei": "490154203237518"
}
}
View Request Parameters

Request Body

FieldTypeRequiredDescription
typestring✅ YesMust be app_client
infoobject✅ YesDevice information (see below)

Info Object

FieldTypeRequiredDescription
titlestring⚠️ RecommendedHuman-readable device name
osstring⚠️ RecommendedOperating system version
modelstring⚠️ RecommendedDevice model
device_idstring⚠️ RecommendedUnique device identifier
imeistring⬜ OptionalIMEI number (if available)

Response

{
"title": "My Mobile App",
"permissions": [
"use_password_grant",
"accept_with_pin"
],
"type": "app_client",
"info": {
"title": "John's iPhone",
"os": "iOS 17.0",
"model": "iPhone 15 Pro",
"device_id": "A1B2C3D4E5F6"
},
"credentials": {
"access_token": "1iGYMlmRJXsxnXmr",
"token_type": "mac",
"mac_key": "lwn46MtHtHbQJU0aMUIK5vsiohVS1Llj",
"mac_algorithm": "hmac-sha-256"
}
}
Store Credentials Securely

The credentials object contains sensitive information. Store it securely on the device and never expose it in logs or to 3rd parties.

Implementation Example
class MobileAppClient {
constructor(applicationCredentials) {
this.appClient = new PayseraClient(applicationCredentials);
}

async registerDevice(deviceInfo) {
try {
// Create new app_client for this device
const response = await this.appClient.createClient({
type: 'app_client',
info: {
title: await this.getDeviceName(),
os: deviceInfo.os,
model: deviceInfo.model,
device_id: deviceInfo.deviceId,
imei: deviceInfo.imei
}
});

// Store credentials securely
await this.secureStorage.save({
accessToken: response.credentials.access_token,
macKey: response.credentials.mac_key,
macAlgorithm: response.credentials.mac_algorithm
});

console.log('✅ Device registered successfully');
return response;

} catch (error) {
console.error('❌ Device registration failed:', error);
throw error;
}
}

async getDeviceName() {
// Platform-specific implementation
if (Platform.OS === 'ios') {
return await DeviceInfo.getDeviceName();
} else {
return await DeviceInfo.getModel();
}
}
}

Advanced Topics

Update Client Configuration

Update client settings and permissions. Only available for private_client type.

Request

PUT /rest/v1/client/{clientId}
Content-Type: application/json
{
"type": "private_client",
"permissions": [
"show_in_frame",
"use_password_grant",
"accept_with_pin"
],
"project_id": 123,
"location_id": 456,
"hosts": [
{
"host": "example.com",
"port": null,
"path": "/payments",
"protocol": "https",
"any_port": true,
"any_subdomain": true
}
]
}

Request Body

FieldTypeRequiredDescription
typestring✅ YesClient type
permissionsarray⚠️ OptionalArray of permission strings
project_idinteger⬜ OptionalAssociated project ID
location_idinteger⬜ OptionalAssociated location ID
hostsarray⬜ OptionalAllowed hosts configuration
Revoking Permissions

If permissions array is empty, all permissions will be revoked!

Get Client Wallet Permissions

Request

GET /rest/v1/client/{clientId}/permissions-to-wallets

Response

[
{
"wallet": {
"id": 1,
"owner": 1234,
"account": {
"number": "EVP1",
"user_id": 1234,
"owner_type": "natural"
}
},
"scopes": ["balance", "statements"]
}
]

Wallet Scopes

ScopeDescription
balanceCan read wallet balance
statementsCan read account statements
Private Client Setup

Setup Process:

  1. Contact Paysera support
  2. Provide integration details
  3. Receive credentials (MAC or SSL)
  4. Start making API calls

Code Example:

const privateClient = new PayseraClient({
type: 'private',
clientId: 'wkVd93h2uS',
macKey: 'IrdTc8uQodU7PRpLzzLTW6wqZAO6tAMU',
macAlgorithm: 'hmac-sha-256'
});

// Can access multiple projects
const projects = await privateClient.getUserProjects('me');

// Can manage wallets
const wallets = await privateClient.getWalletPermissions();
Application Client Setup

Setup Process:

  1. Register mobile application with Paysera
  2. Receive application credentials
  3. Bundle credentials in app package
  4. Create app_client on first run

Code Example:

// Bundled in app (from build configuration)
const applicationClient = new PayseraClient({
type: 'application',
clientId: process.env.APP_CLIENT_ID,
macKey: process.env.APP_MAC_KEY
});

// First run - create device client
if (!await storage.hasCredentials()) {
const deviceClient = await applicationClient.createClient({
type: 'app_client',
info: await getDeviceInfo()
});

await storage.saveCredentials(deviceClient.credentials);
}
App Client Lifecycle

Lifecycle:

  1. Created by application client
  2. Stored securely on device
  3. Used for all API calls
  4. Deleted when app is uninstalled

Code Example:

// Load stored credentials
const credentials = await storage.getCredentials();

const appClient = new PayseraClient({
type: 'app',
accessToken: credentials.accessToken,
macKey: credentials.macKey
});

// Now can use full API
const user = await appClient.getUser('me');
const balance = await appClient.getWalletBalance(user.default_wallet_id);
Best Practices

1. Check Permissions Before Using Features

async function canProcessPayments() {
const client = await api.getClient();
return client.permissions.includes('accept_with_pin') ||
client.permissions.includes('accept_with_flash');
}

if (await canProcessPayments()) {
// Show payment button
} else {
// Show error or request permissions
}

2. Store Device Credentials Securely

// ✅ Good - use secure storage
import SecureStore from 'expo-secure-store';
await SecureStore.setItemAsync('mac_key', credentials.macKey);

// ❌ Bad - don't use AsyncStorage for credentials
await AsyncStorage.setItem('mac_key', credentials.macKey);

3. Handle Client Registration Errors

async function registerDeviceWithRetry(maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await applicationClient.createClient({
type: 'app_client',
info: await getDeviceInfo()
});
} catch (error) {
if (error.code === 'device_already_registered') {
return await storage.getCredentials();
}

if (i === maxRetries - 1) throw error;
await sleep(Math.pow(2, i) * 1000);
}
}
}

4. Validate Client Type Before Operations

async function ensureCorrectClientType(requiredType) {
const client = await api.getClient();

if (client.type !== requiredType) {
throw new Error(
`This operation requires ${requiredType} client, ` +
`but current client is ${client.type}`
);
}
}

// Before creating clients
await ensureCorrectClientType('application');
await api.createClient({ type: 'app_client', ... });
Common Issues

Issue: "forbidden" Error When Creating Client

Cause: Only application clients can create app_client instances.

Solution:

const client = await api.getClient();
if (client.type !== 'application') {
throw new Error('Cannot create app_client - wrong client type');
}

Issue: Lost Device Credentials

Cause: App reinstalled or data cleared.

Solution: Create new app_client:

async function recoverCredentials() {
console.log('Creating new device client...');
const newClient = await applicationClient.createClient({
type: 'app_client',
info: await getDeviceInfo()
});

await storage.saveCredentials(newClient.credentials);
return newClient;
}

Issue: Permission Denied

Cause: Client doesn't have required permission.

Solution:

const client = await api.getClient();
if (!client.permissions.includes('access_statements')) {
throw new Error(
'This client cannot access statements. ' +
'Please contact support to enable this permission.'
);
}

Next Steps