The previous post ended with a promise: building REST APIs that your web and mobile applications can actually use. This post delivers on it.
If you are running a hybrid architecture — IBM i at the transactional core, modern front ends handling the user interface — REST APIs are the bridge between the two. Getting that bridge right determines whether the hybrid model is a clean architecture or a maintenance headache.
This post covers the practical options for exposing IBM i data and business logic as REST APIs, with enough detail to make an informed choice for your environment.
Why REST and not something else
IBM i has supported web services for a long time. There were SOAP-based web services, MQ integrations, sockets-based custom protocols, and flat-file exchanges via FTP. All of them still work. None of them are what a React developer, a mobile team, or a SaaS platform will ask for in 2026.
REST over HTTPS with JSON payloads is the lingua franca of modern software integration. Every language, every framework, every cloud platform speaks it natively. Choosing REST means your IBM i data is consumable by anything without custom adapters or protocol negotiation.
The question is not whether to use REST. The question is which of the several available approaches to use.
Option 1: IBM i Access REST Services (IAS REST)
IBM introduced built-in REST services for IBM i with 7.3 TR7 and continued improving them through subsequent releases. They are available without installing any additional software.
The IAS REST interface exposes DB2 for i as an HTTP endpoint. A GET request to the correct URL with appropriate credentials returns query results as JSON. No custom code required.
What it looks like:
GET /ibmi/v1/db2/sql?sql=SELECT+ORDNO,CUSNO,ORDAMT+FROM+ORDHDR+WHERE+ORDSTS='OP'
Host: your-ibmi-system.example.com
Authorization: Basic [base64 credentials]
Response:
{
"success": true,
"rowCount": 47,
"columns": ["ORDNO", "CUSNO", "ORDAMT"],
"rows": [
["ORD00143", "C01892", 1450.00],
["ORD00144", "C00271", 820.50],
...
]
}Strengths:
- No development required — zero custom code to write or maintain
- Available on any IBM i 7.3+ system with the right PTFs applied
- Handles basic authentication and SSL natively
- Adequate for internal tooling, reporting dashboards, and read-heavy integrations
Limitations:
- Read-only SQL only — no way to call RPG programs or stored procedures directly
- Returns column arrays, not named objects — JSON structure requires transformation on the client
- No API versioning, rate limiting, or fine-grained access control
- Not appropriate for public-facing APIs or external consumers
- Exposes the SQL layer directly — a poorly formed query is a performance risk
IAS REST is the right choice for internal tools built by people who understand IBM i, not for production APIs consumed by external applications.
Option 2: Node.js in PASE
PASE (Portable Application Solutions Environment) is the AIX compatibility layer built into IBM i. It runs a subset of AIX binaries, which includes Node.js. IBM provides official Node.js builds for IBM i through the ibmi-oss-extra repository.
Running Node.js in PASE means you can write a standard Express application that handles HTTP routing, JSON serialisation, authentication middleware, and request validation — exactly as you would on any Linux server. The difference is how it talks to DB2 for i.
The odbc or idb-connector packages connect Node.js directly to DB2 for i without leaving the system. A stored procedure call from Node.js executes in DB2, which can call RPG programs via the QCMDEXC or CALL mechanisms. The RPG layer does what it has always done.
A minimal example:
const express = require('express');
const Database = require('idb-connector').dbconn;
const Statement = require('idb-connector').dbstmt;
const app = express();
app.use(express.json());
app.get('/api/v1/orders/open', (req, res) => {
const conn = new Database();
conn.conn('*LOCAL');
const stmt = new Statement(conn);
stmt.exec(
`SELECT ORDNO, CUSNO, ORDAMT, ORDDAT
FROM ORDHDR
WHERE ORDSTS = 'OP'
ORDER BY ORDDAT DESC
FETCH FIRST 100 ROWS ONLY`,
(rows, err) => {
if (err) {
return res.status(500).json({ error: 'Database error', detail: err.message });
}
res.json({
success: true,
count: rows.length,
orders: rows.map(r => ({
orderNumber: r.ORDNO.trim(),
customerNumber: r.CUSNO.trim(),
amount: parseFloat(r.ORDAMT),
date: r.ORDDAT
}))
});
stmt.close();
conn.disconn();
conn.close();
}
);
});
app.listen(3000, () => console.log('IBM i API running on port 3000'));Calling an RPG program:
app.post('/api/v1/orders', (req, res) => {
const { customerNumber, lines } = req.body;
const conn = new Database();
conn.conn('*LOCAL');
const stmt = new Statement(conn);
// Call RPG order creation program via stored procedure wrapper
stmt.exec(
`CALL ORDLIB.CRTORD('${customerNumber}', ?, ?)`,
(rows, err) => {
if (err) {
return res.status(500).json({ error: err.message });
}
res.status(201).json({ orderNumber: rows[0].ORDNO.trim() });
stmt.close();
conn.disconn();
conn.close();
}
);
});Strengths:
- Full control over API design — request shape, response shape, error handling, versioning
- Can call RPG programs, CL commands, and stored procedures
- Express middleware ecosystem: authentication (JWT, API keys), rate limiting, logging, validation
- Familiar tooling for any developer who knows Node.js
- Runs entirely on IBM i — no separate server to manage
- Can be managed with PM2 for process supervision and restart on failure
Limitations:
- Requires PASE and Node.js installation (straightforward with IBM’s open-source tooling)
- Adds a runtime to manage and keep updated
- PASE resource limits apply — not suitable for very high-throughput API workloads
- Connection pooling needs care — idb-connector is synchronous; async patterns require a wrapper
This is the most practical option for most shops building new REST APIs on IBM i. The investment in learning is low for anyone already familiar with JavaScript, and the result is a properly designed API that any consumer can use.
Option 3: PHP in PASE
PHP runs in PASE alongside Node.js and has a longer history on IBM i. The ibm_db2 PHP extension provides native DB2 connectivity. Slim Framework or Laravel can handle routing.
The pattern is essentially the same as Node.js: PHP handles HTTP concerns, DB2 extension handles data access, RPG programs are called via stored procedures.
PHP is the better choice if your team has existing PHP expertise or if you are integrating IBM i with a PHP-based application (WordPress, Drupal, or a custom PHP application). If your team knows JavaScript better than PHP, Node.js is the cleaner path.
Option 4: RPG CGI / ILE Web
This is the oldest approach — RPG programs that run directly as HTTP handlers under the IBM HTTP Server (Apache on IBM i). A request arrives, Apache maps the URL to a program, the program executes and writes the HTTP response directly.
ILE Web and CGIDEV2 are toolkits that make this less painful. They handle HTTP parsing, URL routing, and response building from within RPG.
When to use it:
- Environments where PASE is not available or not permitted
- Teams with deep RPG expertise and no JavaScript capability
- Existing CGI programs that need incremental improvement rather than replacement
When not to use it:
- New API development in a shop with any JavaScript capability
- Public-facing APIs requiring modern auth, versioning, and rate limiting
- Environments where modern developers need to work on the API layer
RPG CGI works. It is also a pattern that is harder to find developers for, harder to test, and harder to maintain than a Node.js or PHP alternative.
Option 5: API Gateway in front of IBM i
For larger organisations, the cleanest architecture is a dedicated API gateway — MuleSoft, Azure API Management, AWS API Gateway, or IBM API Connect — sitting between consumers and IBM i.
The gateway handles everything external-facing: authentication, rate limiting, versioning, API key management, request transformation, caching, and monitoring. Behind the gateway, IBM i exposes a simpler internal service (Node.js in PASE, or even IAS REST), and the gateway handles the production hardening.
┌─────────────────────────────────────────────────────────┐
│ External Consumers (Web, Mobile, Partners, Microservices)│
└──────────────────────┬──────────────────────────────────┘
│ HTTPS
▼
┌─────────────────────────────────────────────────────────┐
│ API Gateway (MuleSoft / Azure APIM) │
│ Auth | Rate Limiting | Versioning | Monitoring | Cache │
└──────────────────────┬──────────────────────────────────┘
│ Internal HTTPS
▼
┌─────────────────────────────────────────────────────────┐
│ IBM i (Node.js in PASE) │
│ Simple Express API — no auth/rate-limit concerns │
│ Calls DB2 and RPG programs directly │
└─────────────────────────────────────────────────────────┘This separation of concerns means the IBM i layer stays simple and focused on business logic, while the gateway handles the operational concerns that change more frequently.
When this is the right choice:
- Multiple external consumers (partners, customer portals, mobile apps) all hitting the same IBM i data
- Regulatory requirements for API monitoring, audit logging, or rate limiting
- Organisations with an existing API management platform
- Multiple IBM i systems (or IBM i plus other backends) that need a unified API surface
Authentication patterns for IBM i REST APIs
This is where many IBM i REST implementations fall down — they use IBM i native profile credentials for API authentication. That means API consumers hold IBM i usernames and passwords, which is a significant security and operational risk.
Better patterns:
JWT (JSON Web Tokens) — the API consumer authenticates once to an identity provider (the Node.js layer, or an external IdP like Azure AD) and receives a signed JWT. Subsequent API calls include the JWT in the Authorization header. The API validates the token signature without calling IBM i security on every request.
API keys — issued to each consumer, stored (hashed) in DB2 or a separate store. The middleware validates the key before routing the request. Suitable for server-to-server integrations where human authentication is not involved.
OAuth 2.0 — the appropriate choice when consumer applications are acting on behalf of human users. Azure AD, Okta, or Keycloak handle the OAuth flow. The IBM i API trusts tokens issued by the IdP.
What to avoid: Basic authentication with IBM i native profile credentials over the network, even over HTTPS. If those credentials are compromised, the attacker has IBM i OS access, not just API access.
Practical considerations for production deployments
A few things that come up when moving from prototype to production:
Connection pooling. Opening a new DB2 connection per request does not scale. Use a connection pool — node-ibmi-pool or a custom pool around idb-connector — and size it appropriately for your expected concurrent request volume.
Error handling. IBM i DB2 errors and RPG program exceptions need to be caught and translated to appropriate HTTP status codes and JSON error responses. A raw DB2 error message in a 500 response is not useful to a React developer debugging an integration.
Logging. Request and response logging, with correlation IDs, makes debugging integration issues tractable. Winston or Pino work well in Node.js on PASE. Log to IBM i IFS files and rotate them.
Process management. PM2 running in PASE keeps your Node.js API processes alive across restarts, manages log rotation, and provides a simple CLI for status monitoring. Configure it to start on system IPL via the PASE autostart mechanism.
SSL/TLS. Either terminate SSL at a reverse proxy (HAProxy, Nginx in PASE, or an external load balancer) or configure Node.js with a certificate. IBM i’s Digital Certificate Manager manages certificates for the system; the PASE layer can reference them.
Testing IBM i REST APIs
A Node.js Express API running in PASE is testable with standard tools. Jest or Mocha for unit tests. Supertest for HTTP integration tests against the running API. Postman or Bruno for manual exploration and contract testing.
The IBM i DB2 calls can be mocked in unit tests so they run on a developer’s laptop without needing an IBM i system. Integration tests run against a development IBM i partition.
This testability is a genuine advantage of the Node.js approach over RPG CGI — testing CGI programs requires the full IBM i stack. Testing an Express application does not.
Choosing the right approach
A practical decision guide:
Internal tooling, read-only, small team: IAS REST. No code to write, quick to implement.
New API development, team knows JavaScript: Node.js in PASE with Express. Full control, maintainable, testable.
New API development, team knows PHP: PHP in PASE with Slim or Laravel.
Existing RPG expertise, no PASE: RPG CGI with ILE Web or CGIDEV2.
Enterprise, multiple consumers, existing API management platform: Node.js in PASE behind an API gateway.
Large organisation, complex integration requirements: MuleSoft or Azure API Management with IBM i connectors.
The good news is that the Node.js in PASE option is available to any IBM i 7.3+ shop, requires no additional IBM licensing, and produces APIs that look and behave exactly like APIs from any other platform. The consumers of your IBM i REST API do not need to know, or care, that the data comes from IBM i.
Next post: Security hardening for modern IBM i — object authority, exit programs, network configuration, and what good IBM i security practice looks like in 2026.