Upload Shift Information (T163)
Upload shift closing data from Electronic Dispensing Controllers (EDC) to the EFRIS system. This endpoint records start/end volumes, sales amounts, and operational details for specific fuel pumps, nozzles, and tanks at the end of a shift. Request is encrypted; response is unencrypted.
Endpoint Overview
| Property | Value |
|---|---|
| Interface Code | T163 |
| Request Encrypted | ✅ Yes |
| Response Encrypted | ❌ No |
| Request Body | { "shiftNo": "...", "startVolume": "...", ... } |
| Response Format | JSON (Standard Envelope) |
Flow Description
- Client collects shift data from EDC controller (start/end meter readings, sales totals).
- Client submits shift information via T163 with encrypted payload.
- Server validates shift data against registered pump/nozzle/tank configurations.
- Server records shift data for reconciliation with uploaded invoices (T167).
- Client receives confirmation (null content on success).
💡 Tip: Call T163 at the end of each operator shift. Ensure
startVolumematches the previous shift'sendVolumefor continuity. Use T162 to validatefuelTypevalues before submission.
- PHP
- JavaScript / TypeScript
- Python
try {
// Call T163: Upload Shift Information
$shiftData = [
'shiftNo' => '20250219-01',
'startVolume' => '851.91',
'endVolume' => '951.91',
'fuelType' => 'Kerosene',
'goodsId' => '12344',
'goodsCode' => 'Kerosene_01',
'invoiceAmount' => '221.31',
'invoiceNumber' => '16',
'nozzleNo' => 'nozzle_01_0001',
'pumpNo' => 'pump_01_0001',
'tankNo' => 'tank_01_0001',
'userName' => 'Kerwin',
'userCode' => 'kerwin0001',
'startTime' => '2025-02-19 10:59:14',
'endTime' => '2025-02-19 18:59:14'
];
$response = $client->uploadShiftInfo($shiftData);
// Response content is typically null/empty on success
echo "✅ Shift information uploaded successfully\n";
echo " Shift No: {$shiftData['shiftNo']}\n";
echo " Fuel Type: {$shiftData['fuelType']}\n";
echo " Volume Sold: " . ($shiftData['endVolume'] - $shiftData['startVolume']) . "\n";
} catch (\UraEfrisSdk\Exceptions\APIException $e) {
echo "❌ Upload failed: " . $e->getMessage() . "\n";
echo " Return Code: " . $e->getReturnCode() . "\n";
}
try {
// Call T163: Upload Shift Information
const shiftData = {
shiftNo: '20250219-01',
startVolume: '851.91',
endVolume: '951.91',
fuelType: 'Kerosene',
goodsId: '12344',
goodsCode: 'Kerosene_01',
invoiceAmount: '221.31',
invoiceNumber: '16',
nozzleNo: 'nozzle_01_0001',
pumpNo: 'pump_01_0001',
tankNo: 'tank_01_0001',
userName: 'Kerwin',
userCode: 'kerwin0001',
startTime: '2025-02-19 10:59:14',
endTime: '2025-02-19 18:59:14'
};
const response = await client.uploadShiftInfo(shiftData);
// Response content is typically null/empty on success
console.log('✅ Shift information uploaded successfully');
console.log(' Shift No:', shiftData.shiftNo);
console.log(' Fuel Type:', shiftData.fuelType);
console.log(' Volume Sold:', parseFloat(shiftData.endVolume) - parseFloat(shiftData.startVolume));
} catch (error: any) {
console.error(`❌ Upload failed: ${error.message}`);
if (error.returnCode) {
console.error(` Return Code: ${error.returnCode}`);
}
throw error;
}
try:
# Call T163: Upload Shift Information
shift_data = {
"shiftNo": "20250219-01",
"startVolume": "851.91",
"endVolume": "951.91",
"fuelType": "Kerosene",
"goodsId": "12344",
"goodsCode": "Kerosene_01",
"invoiceAmount": "221.31",
"invoiceNumber": "16",
"nozzleNo": "nozzle_01_0001",
"pumpNo": "pump_01_0001",
"tankNo": "tank_01_0001",
"userName": "Kerwin",
"userCode": "kerwin0001",
"startTime": "2025-02-19 10:59:14",
"endTime": "2025-02-19 18:59:14"
}
response = client.upload_shift_info(shift_data)
# Response content is typically null/empty on success
print("✅ Shift information uploaded successfully")
print(f" Shift No: {shift_data['shiftNo']}")
print(f" Fuel Type: {shift_data['fuelType']}")
print(f" Volume Sold: {float(shift_data['endVolume']) - float(shift_data['startVolume'])}")
except Exception as e:
print(f"❌ Upload failed: {e}")
if hasattr(e, "return_code"):
print(f" Return Code: {e.return_code}")
raise
Request Structure
{
"data": {
"content": "BASE64_ENCRYPTED_PAYLOAD",
"signature": "JKQWJK34K32JJEK2JQWJ5678",
"dataDescription": {
"codeType": "1",
"encryptCode": "2",
"zipCode": "0"
}
},
"globalInfo": {
"interfaceCode": "T163",
"appId": "AP04",
"version": "1.1.20191201",
"tin": "1000029771",
"deviceNo": "TCS9e0df01728335239",
"taxpayerID": "1"
}
}
Request Fields (Encrypted Payload)
| Field | Required | Type | Length | Description |
|---|---|---|---|---|
shiftNo | ✅ Yes | String | ≤20 | Unique shift identifier (e.g., YYYYMMDD-01) |
startVolume | ✅ Yes | Number | - | Meter reading at shift start (integer ≤12, decimal ≤2) |
endVolume | ✅ Yes | Number | - | Meter reading at shift end (integer ≤12, decimal ≤2) |
fuelType | ✅ Yes | String | ≤200 | Fuel type name (must match T162 fuel types) |
goodsId | ✅ Yes | String | ≤18 | Goods ID linked to fuel type from T130 |
goodsCode | ✅ Yes | String | ≤50 | Goods code linked to fuel type from T130 |
invoiceAmount | ✅ Yes | Number | - | Total sales amount for the shift (integer ≤12, decimal ≤2) |
invoiceNumber | ✅ Yes | Number | ≤50 | Count of invoices issued during shift |
nozzleNo | ✅ Yes | String | ≤50 | Nozzle identifier from T169 |
pumpNo | ✅ Yes | String | ≤50 | Pump identifier from T169 |
tankNo | ✅ Yes | String | ≤50 | Tank identifier from T169 |
userName | ✅ Yes | String | ≤500 | Operator name |
userCode | ✅ Yes | String | ≤100 | Operator account code |
startTime | ✅ Yes | String | 20 | Shift start time (yyyy-MM-dd HH:mm:ss) |
endTime | ✅ Yes | String | 20 | Shift end time (yyyy-MM-dd HH:mm:ss) |
💡 Tip: Ensure
endTimeis greater thanstartTime. Volume calculations (endVolume-startVolume) should match expected sales based oninvoiceAmount.
Response Structure
{
"globalInfo": {
"interfaceCode": "T163",
"returnStateInfo": {
"returnCode": "00",
"returnMessage": "SUCCESS"
}
}
}
📋 Note: On success, the
data.contentis typically null or empty. Validation results are returned viaglobalInfo.returnStateInfo.
Response Fields
Global Info
| Field | Required | Type | Description |
|---|---|---|---|
interfaceCode | ✅ Yes | String (5) | Echoes T163 |
returnStateInfo | ✅ Yes | Object | Contains returnCode and returnMessage |
Return State Info
| Field | Required | Type | Description |
|---|---|---|---|
returnCode | ✅ Yes | String | 00 = Success, otherwise error code |
returnMessage | ✅ Yes | String | Human-readable status message |
Return Codes
| Code | Message | Description |
|---|---|---|
00 | SUCCESS | Shift information uploaded successfully |
99 | Unknown error | Generic server error |
400 | Device does not exist | deviceNo not registered for this TIN |
402 | Device key expired | Device credentials expired; re-run T102 |
403 | Device status is abnormal | Device blocked or suspended |
2933 | shiftNo: cannot be empty! | Missing shift number |
2934 | shiftNo: Byte length cannot be greater than 20! | Shift number exceeds length limit |
2935 | startVolume: cannot be empty! | Missing start volume |
2936 | startVolume: The integer character length cannot exceed 12, and the decimal character length cannot exceed 2! | Start volume format error |
2940 | endVolume: cannot be empty! | Missing end volume |
2941 | endVolume: The integer character length cannot exceed 12, and the decimal character length cannot exceed 2! | End volume format error |
2945 | fuelType: cannot be empty! | Missing fuel type |
2946 | fuelType: Byte length cannot be greater than 200! | Fuel type name exceeds limit |
2947 | goodsId: cannot be empty! | Missing goods ID |
2948 | goodsId: Byte length cannot be greater than 18! | Goods ID exceeds limit |
2949 | goodsCode: cannot be empty! | Missing goods code |
2950 | goodsCode: Byte length cannot be greater than 50! | Goods code exceeds limit |
2951 | invoiceNumber: cannot be empty! | Missing invoice count |
2956 | nozzleNo: cannot be empty! | Missing nozzle number |
2958 | pumpNo: cannot be empty! | Missing pump number |
2960 | tankNo: cannot be empty! | Missing tank number |
2962 | userName: cannot be empty! | Missing user name |
2964 | userCode: cannot be empty! | Missing user code |
2966 | startTime: cannot be empty! | Missing start time |
2967 | startTime: The time format must be yyyy-MM-dd HH:mm:ss | Invalid start time format |
2968 | endTime: cannot be empty! | Missing end time |
2969 | endTime: The time format must be yyyy-MM-dd HH:mm:ss | Invalid end time format |
2974 | edcDetails-->nozzleNo: NozzleNo error | Nozzle not registered/invalid |
2975 | edcDetails-->tankNo: Does not match 'nozzleNo' | Tank/nozzle mismatch |
2976 | edcDetails-->pumpNo: Does not match 'nozzleNo' | Pump/nozzle mismatch |
💡 Tip: Errors
2974-2976indicate configuration mismatches. Use T169 to verify pump/nozzle/tank relationships before uploading shift data.
Common Use Cases
-
Shift Closing Operations
Submit meter readings and sales totals at the end of each operator shift for reconciliation. -
EDC Sales Reconciliation
Compare shift volume data with uploaded invoices (T167) to identify discrepancies or potential leakage. -
Operator Performance Tracking
Track sales performance byuserCodeanduserNameacross different shifts. -
Fuel Inventory Management
UsestartVolume/endVolumedata to calculate fuel dispensed and update tank inventory levels. -
Audit Trail Maintenance
Maintain historical records of shift operations for tax audits and compliance verification. -
Multi-Pump Station Management
Upload shift data for multiple pumps/nozzles simultaneously (separate T163 calls per nozzle/pump combination).
Integration Checklist
✅ Validate fuelType against T162 query results before submission
✅ Ensure goodsId and goodsCode match registered fuel products from T130
✅ Verify pump/nozzle/tank relationships via T169 before uploading shift data
✅ Ensure endTime is greater than startTime to avoid validation errors
✅ Validate volume calculations (endVolume ≥ startVolume) before submission
✅ Handle null/empty response content gracefully on success
✅ Log shift submissions for audit trails and discrepancy investigation
✅ Implement retry logic for network failures during shift closing
✅ Ensure shiftNo is unique per pump/nozzle per day
✅ Cross-reference invoiceAmount with actual invoices issued during shift