Client Initialization (T102)
Initialize your EFRIS client by retrieving the server's public key and encrypted client private key. This endpoint establishes the cryptographic foundation for secure communication and does not require prior authentication.
Endpoint Overview
| Property | Value |
|---|---|
| Interface Code | T102 |
| Request Encrypted | ❌ No |
| Response Encrypted | ❌ No |
| Request Body | { "otp": "100983" } (optional) |
| Response Format | JSON |
Flow Description
- Client requests the RSA private key for the registered device.
- Server verifies that
tinmatchesdeviceNoand device status is normal. - Server retrieves the device's private key, encrypts it via white-box encryption, and returns
clientPriKey+keyTable. - Client stores the encrypted credentials for subsequent decryption operations.
🔐 Security Note: The
clientPriKeyis encrypted using white-box cryptography. StorekeyTablesecurely—it is required to decrypt the private key locally.
- PHP
- JavaScript / TypeScript
- Python
try {
// Call T102: Client Initialization
// Optional: pass OTP if required by your deployment
$response = $client->clientInit(['otp' => '100983']);
$content = $response['data']['content'] ?? $response;
if (isset($content['serverPubKey'], $content['clientPriKey'], $content['keyTable'])) {
echo "✅ Initialization successful\n";
echo " Server PubKey: " . substr($content['serverPubKey'], 0, 30) . "...\n";
// Store credentials securely for later use
$keyClient->setClientPrivateKey($content['clientPriKey']);
$keyClient->setKeyTable($content['keyTable']);
$keyClient->setServerPublicKey($content['serverPubKey']);
} else {
echo "⚠️ Missing required keys in response\n";
}
} catch (\UraEfrisSdk\Exceptions\APIException $e) {
echo "❌ API Error: " . $e->getMessage() . "\n";
echo " Return Code: " . $e->getReturnCode() . "\n";
}
try {
// Call T102: Client Initialization
// Optional: pass OTP if required by your deployment
const response = await client.clientInit({ otp: '100983' });
const content = response?.data?.content ?? response;
if (content?.serverPubKey && content?.clientPriKey && content?.keyTable) {
console.log('✅ Initialization successful');
console.log(` Server PubKey: ${content.serverPubKey.substring(0, 30)}...`);
// Store credentials securely for later use
keyClient.setClientPrivateKey(content.clientPriKey);
keyClient.setKeyTable(content.keyTable);
keyClient.setServerPublicKey(content.serverPubKey);
return content;
} else {
console.warn('⚠️ Missing required keys in response');
return null;
}
} catch (error: any) {
console.error(`❌ API Error: ${error.message}`);
if (error.returnCode) {
console.error(` Return Code: ${error.returnCode}`);
}
throw error;
}
try:
# Call T102: Client Initialization
# Optional: pass OTP if required by your deployment
response = client.client_init(otp='100983')
content = response.get("data", {}).get("content", response)
if all(k in content for k in ['serverPubKey', 'clientPriKey', 'keyTable']):
print("✅ Initialization successful")
print(f" Server PubKey: {content['serverPubKey'][:30]}...")
# Store credentials securely for later use
key_client.set_client_private_key(content['clientPriKey'])
key_client.set_key_table(content['keyTable'])
key_client.set_server_public_key(content['serverPubKey'])
return content
else:
print("⚠️ Missing required keys in response")
return None
except Exception as e:
print(f"❌ API Error: {e}")
if hasattr(e, 'return_code'):
print(f" Return Code: {e.return_code}")
raise
Response Structure
{
"data": {
"content": {
"clientPriKey": "vovhW9PY7YUPA98X36BSM8V1OA3gSyF+nTNWAeiVsXMIc",
"serverPubKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQ...",
"keyTable": "OiJ2b3ZoVzlQWTdZVVBBOThYMzZCU004VjFPQTN..."
}
},
"globalInfo": {
"interfaceCode": "T102",
"returnStateInfo": {
"returnCode": "00",
"returnMessage": "SUCCESS"
}
}
}
Response Fields
| Field | Required | Type | Description |
|---|---|---|---|
clientPriKey | ✅ Yes | String | Encrypted client RSA private key (white-box). Used to decrypt server responses. Only available when appId is AP01. |
serverPubKey | ✅ Yes | String | Server's RSA public key. Used to verify signatures on server responses. |
keyTable | ✅ Yes | String | White-box decryption table. Required to decrypt clientPriKey locally. |
Return Codes
| Code | Message | Description |
|---|---|---|
00 | SUCCESS | Initialization completed; keys returned |
99 | Unknown error | Generic server error |
06 | The outer message is empty | Malformed request envelope |
07 | GlobalInfo content cannot be empty | Missing required globalInfo |
11 | InterfaceCode cannot be empty | Missing interfaceCode in request |
400 | Device does not exist | deviceNo not registered for this TIN |
401 | Device key does not exist | No cryptographic key found for device |
402 | Device key expired | Device credentials have expired |
403 | Device status is abnormal | Device is blocked, suspended, or inactive |
💡 Tip: Call this endpoint once per session after verifying time sync (T101). Cache the returned keys securely—do not re-fetch on every API call.
Common Use Cases
-
Session Bootstrap
Establish cryptographic context before calling authenticated endpoints likeT103: Sign In. -
Key Rotation Handling
Re-initialize when receiving402(key expired) to fetch updated credentials. -
Multi-Device Support
Initialize separateKeyClientinstances perdeviceNofor taxpayers operating multiple fiscal devices. -
Offline Mode Preparation
CacheserverPubKeyto enable offline invoice signing when network is unavailable.