App Server Sample Code
JavaScript sample code of the App Server. Docker image of the sample code is available. Sample code of other languages will be released in the future.
const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const morgan = require('morgan');
// Load environment variables from config.env if it exists, otherwise use system env vars
try {
require('dotenv').config({path: './config.env'});
} catch (error) {
// config.env not found, use system environment variables
require('dotenv').config();
}
const app = express();
const PORT = process.env.PORT || 3000;
const LISTEN_HOST = process.env.LISTEN_HOST || "127.0.0.1";
// PalmID Configuration
const PALMID_CONFIG = {
entrypoint: process.env.PMS_ENTRYPOINT || 'https://api2.palmid.com/saas',
apiKey: process.env.PMS_API_KEY
};
if (!PALMID_CONFIG.apiKey) {
console.error('❌ PMS_API_KEY is required');
process.exit(1);
}
// Middleware
app.use(helmet()); // Security headers
app.use(cors()); // Enable CORS
app.use(morgan('combined')); // Logging
app.use(express.json()); // Parse JSON bodies
app.use(express.urlencoded({extended: true})); // Parse URL-encoded bodies
// Routes
app.get('/health', (req, res) => {
res.json({
status: 'healthy',
timestamp: new Date().toISOString(),
uptime: process.uptime()
});
});
// API Routes
// Session endpoint
app.get('/session/get_id', async (req, res) => {
try {
const projectId = req.headers['pms-project-id'];
if (!projectId) {
return res.status(400).json({
success: false,
error: 'pms-project-id header is required'
});
}
const headers = {
"Content-Type": "application/json",
"pms-project-id": projectId,
};
if (PALMID_CONFIG.apiKey) {
headers.Authorization = `Bearer ${PALMID_CONFIG.apiKey}`;
}
const response = await fetch(`${PALMID_CONFIG.entrypoint}/session/get_id`, {
headers,
});
if (!response.ok) {
throw new Error(`Remote error: ${response.status}`);
}
const data = await response.json();
const sessionId = data.sessionId;
if (!sessionId) {
throw new Error(`Failed to retrieve session ID`);
}
res.json({
success: true,
sessionId: sessionId
});
} catch (error) {
console.error('Session error:', error.message);
res.status(500).json({
success: false,
error: error.message
});
}
});
// Session verify endpoint
app.post('/session/verify', async (req, res) => {
const sessionId = req.body.sessionId;
const projectId = req.headers['pms-project-id'];
if (!sessionId) {
return res.status(400).json({
success: false,
error: 'sessionId is required in request body'
});
}
if (!projectId) {
return res.status(400).json({
success: false,
error: 'pms-project-id header is required'
});
}
try {
const headers = {
"Content-Type": "application/json",
"pms-project-id": projectId,
};
if (PALMID_CONFIG.apiKey) {
headers.Authorization = `Bearer ${PALMID_CONFIG.apiKey}`;
}
const response = await fetch(`${PALMID_CONFIG.entrypoint}/session/verify`, {
method: "POST",
headers,
body: JSON.stringify({
sessionId,
}),
});
const data = await response.json();
if (!response.ok) {
console.error(`Verify failed:`, data);
res.status(response.status).json(data);
} else {
// If the session is verified, we can get the result from the data object
if (data.resultCode === 0) {
// If the session is verified, we can get the result from the data object
const result = data.result;
if (result.is_match !== undefined) {
// User verification result, get the is_match, score and user id
const isMatch = result.is_match;
const matchScore = result.score;
const userId = result.id;
} else {
// User registration result, get the new registered user id
const userId = result.id;
}
} else if (data.resultCode === 10009) {
// User registration failed with duplicate palm
const duplicateUserId = data.result.duplicateId;
}
res.json(data);
}
//=================================
// Insert your code here to process the result.
// Case 1: store userId in your user database.
// Case 2: approve a transaction upon a successful verification
//=================================
} catch (err) {
console.error("Failed to fetch session ID:", err.message);
res.status(500).json({
success: false,
error: err.message
});
}
});
// Error handling middleware
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({
error: 'Something went wrong!',
message: process.env.NODE_ENV === 'development' ? err.message : 'Internal server error'
});
});
// 404 handler
app.use((req, res) => {
res.status(404).json({
error: 'Route not found',
path: req.originalUrl
});
});
// Start server
app.listen(PORT, LISTEN_HOST, () => {
console.log(`🚀 Server is running on port ${PORT}`);
console.log(`📱 Environment: ${process.env.NODE_ENV || 'development'}`);
console.log(`🔗 Health check: http://${LISTEN_HOST}:${PORT}/health`);
console.log(`🔑 API Key configured: ${PALMID_CONFIG.apiKey ? 'Yes' : 'No'}`);
console.log(`🌐 PalmID PMS Entrypoint: ${PALMID_CONFIG.entrypoint}`);
});
module.exports = app;
13 August 2025