CICS Web Services: Exposing Mainframe Logic as REST and SOAP APIs

Introduction: CICS as a Modern API Gateway
For decades, CICS was synonymous with 3270 green-screen terminals. But CICS has evolved dramatically. Modern CICS — IBM CICS Transaction Server 6.x on z/OS — is a fully capable web application server that can expose existing COBOL business logic as REST APIs, SOAP web services, and JSON microservices, without rewriting a line of the original COBOL code.
This is enormously valuable for enterprise modernisation: instead of rewriting trusted, validated COBOL business logic (with all the risk, cost, and regression testing that entails), organisations can wrap CICS programs with a web API layer and let modern front ends — mobile apps, web applications, Node.js microservices — call the mainframe directly. The CICS program runs unchanged; only the interface layer is added.
This guide covers CICS web services architecture, key resource definitions, and how COBOL programs interact with HTTP requests and JSON data through CICS channels and containers.
CICS Web Support Architecture
When an HTTP request arrives at a CICS region, it flows through the following layers:
Client (browser, mobile app, API)
│ HTTP/HTTPS
▼
CICS TCP/IP Listener (port 80/443 defined by TCPIPSERVICE)
│
▼
CICS Web Support (URIMAP routing)
│ Matches URI path + HTTP method
▼
CICS PIPELINE (message transformation chain)
│ JSON/XML parsing, SOAP envelope handling
▼
CICS COBOL Program (business logic, unchanged)
│ EXEC CICS GET/PUT CONTAINER
▼
Response flows back through PIPELINE → HTTP responseThe four key CICS resources for web services:
| Resource | Purpose |
|---|---|
| TCPIPSERVICE | Defines the TCP/IP port and protocol (HTTP/HTTPS) |
| URIMAP | Maps URI path + HTTP method to a pipeline or program |
| PIPELINE | Defines the message processing chain |
| WEBSERVICE | (SOAP) Associates the WSDL with the service binding |
Defining Web Services: CSD Resources
TCPIPSERVICE
CEDA DEFINE TCPIPSERVICE(HTTPPORT)
GROUP(WEBSVCS)
PORTNUMBER(3001) /* HTTP port for web services */
PROTOCOL(HTTP) /* HTTP (use HTTPS for production) */
SOCKETCLOSE(60)
MAXDATALEN(32768)
BACKLOG(10)URIMAP (Provider — Serving Requests)
CEDA DEFINE URIMAP(EMPGET)
GROUP(WEBSVCS)
USAGE(PIPELINE)
HOST(*) /* Any hostname */
PATH(/api/employee/*) /* URI path pattern */
SCHEME(HTTP)
PIPELINE(JSONPIPE) /* Which pipeline to use */
WEBSERVICE(EMPWS) /* WEBSERVICE resource (for SOAP) */
TRANSACTION(APIG) /* CICS transaction to use */
USERID(APIUSER)PIPELINE
CEDA DEFINE PIPELINE(JSONPIPE)
GROUP(WEBSVCS)
CONFIGFILE(/cics/pipelines/jsonhandler.xml)
SHELF(/cics/pipelines/shelf)
WSDIR(/cics/pipelines/wsdl)The pipeline configuration XML specifies which message handlers to apply. For a simple JSON REST pipeline:
<?xml version="1.0"?>
<provider_pipeline xmlns="http://www.ibm.com/software/htp/cics/pipeline"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<service>
<terminal_handler>
<cics_json_channel_handler>
<request_container>DFHWS-DATA</request_container>
<response_container>DFHWS-DATA</response_container>
</cics_json_channel_handler>
</terminal_handler>
</service>
</provider_pipeline>CICS Channels and Containers
Modern CICS web services use channels and containers to pass data between the pipeline and the application program. A channel is a named collection of containers (key-value pairs). A container holds one data item (the request body, a header, a status code).
This replaces the COMMAREA for web service interactions (COMMAREA is limited to 32 KB; containers can hold megabytes of data).
Key Predefined Containers for Web Services
| Container Name | Content |
|---|---|
| DFHWS-DATA | The request/response body (JSON, XML, or SOAP body) |
| DFHWS-BODY | Full HTTP body |
| DFHHTTP-REQUEST | HTTP request details |
| DFHRESPONSE | HTTP response status code |
A COBOL Program as a REST API Handler
Here is a CICS COBOL program that handles a GET /api/employee/{empno} REST request:
IDENTIFICATION DIVISION.
PROGRAM-ID. EMPAPI.
*── This program is invoked by CICS web support when a GET
*── request arrives for /api/employee/*
*── Request: HTTP GET /api/employee/000100
*── Response: JSON { "empNo": "000100", "name": "...", "salary": ... }
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-CHANNEL PIC X(16).
01 WS-CONT-LEN PIC S9(8) COMP VALUE ZERO.
01 WS-RESP PIC S9(8) COMP VALUE ZERO.
01 WS-HTTP-STATUS PIC S9(4) COMP VALUE ZERO.
*── Request data (from DFHWS-DATA container - JSON input)
01 WS-REQUEST-JSON PIC X(1024).
01 WS-REQUEST-LEN PIC S9(8) COMP VALUE +1024.
*── Employee record
01 WS-EMP-KEY PIC X(6).
01 WS-EMP-REC.
05 WS-EMP-NO PIC X(6).
05 WS-EMP-NM PIC X(30).
05 WS-EMP-SAL PIC S9(7)V99 COMP-3.
01 WS-EMP-LEN PIC S9(4) COMP VALUE +43.
*── Response JSON (hand-built for simplicity)
01 WS-RESPONSE-JSON PIC X(512).
01 WS-RESP-LEN PIC S9(8) COMP VALUE ZERO.
LINKAGE SECTION.
01 DFHCOMMAREA PIC X. *> Not used — web services use channels
PROCEDURE DIVISION.
MAIN-LOGIC.
*── Get the current channel name ─────────────────────────────
EXEC CICS ASSIGN CHANNEL(WS-CHANNEL) RESP(WS-RESP) END-EXEC
*── Get the request data from the DFHWS-DATA container ───────
EXEC CICS GET CONTAINER('DFHWS-DATA')
CHANNEL(WS-CHANNEL)
INTO(WS-REQUEST-JSON)
FLENGTH(WS-REQUEST-LEN)
RESP(WS-RESP)
END-EXEC
*── Extract employee key from request (simplified) ───────────
*── In production, use CICS JSON binding or parse manually ───
MOVE WS-REQUEST-JSON(1:6) TO WS-EMP-KEY
*── Look up employee ─────────────────────────────────────────
EXEC CICS READ FILE('EMPFILE')
RIDFLD(WS-EMP-KEY)
INTO(WS-EMP-REC)
LENGTH(WS-EMP-LEN)
RESP(WS-RESP)
END-EXEC
EVALUATE WS-RESP
WHEN DFHRESP(NORMAL)
PERFORM BUILD-SUCCESS-RESPONSE
MOVE 200 TO WS-HTTP-STATUS
WHEN DFHRESP(NOTFND)
MOVE '{"error":"Employee not found"}' TO WS-RESPONSE-JSON
MOVE 30 TO WS-RESP-LEN
MOVE 404 TO WS-HTTP-STATUS
WHEN OTHER
MOVE '{"error":"Internal server error"}' TO WS-RESPONSE-JSON
MOVE 34 TO WS-RESP-LEN
MOVE 500 TO WS-HTTP-STATUS
END-EVALUATE
*── Write JSON response to DFHWS-DATA container ──────────────
EXEC CICS PUT CONTAINER('DFHWS-DATA')
CHANNEL(WS-CHANNEL)
FROM(WS-RESPONSE-JSON)
FLENGTH(WS-RESP-LEN)
DATATYPE(CHAR)
END-EXEC
*── Set HTTP status code ──────────────────────────────────────
EXEC CICS PUT CONTAINER('DFHRESPONSE')
CHANNEL(WS-CHANNEL)
FROM(WS-HTTP-STATUS)
FLENGTH(LENGTH OF WS-HTTP-STATUS)
END-EXEC
EXEC CICS RETURN END-EXEC.
BUILD-SUCCESS-RESPONSE.
STRING '{"empNo":"' WS-EMP-NO
'","name":"' FUNCTION TRIM(WS-EMP-NM)
'","salary":' WS-EMP-SAL
'}'
DELIMITED SIZE INTO WS-RESPONSE-JSON
MOVE FUNCTION LENGTH(FUNCTION TRIM(WS-RESPONSE-JSON))
TO WS-RESP-LEN.CICS as a Web Service Requester (Calling External APIs)
CICS can also act as a web service requester — calling external REST or SOAP APIs from within a CICS COBOL program. This enables CICS to consume microservices, cloud APIs, or third-party web services:
*── Call an external REST API from CICS ──────────────────────────
CALL-EXTERNAL-API.
EXEC CICS WEB OPEN
SESSTOKEN(WS-SESSION-TOKEN)
HOST('api.example.com')
HOSTLENGTH(15)
HTTPSPORT(443)
SCHEME(HTTPS)
RESP(WS-RESP)
END-EXEC
IF WS-RESP NOT = DFHRESP(NORMAL)
PERFORM HANDLE-WEB-OPEN-ERROR
GO TO END-CALL
END-IF
EXEC CICS WEB SEND
SESSTOKEN(WS-SESSION-TOKEN)
PATH('/v1/validate')
PATHLENGTH(11)
METHOD(GET)
MEDIATYPE('application/json')
FROM(WS-REQUEST-JSON)
FROMLENGTH(WS-REQUEST-LEN)
RESP(WS-RESP)
END-EXEC
EXEC CICS WEB RECEIVE
SESSTOKEN(WS-SESSION-TOKEN)
INTO(WS-RESPONSE-JSON)
LENGTH(WS-RESPONSE-LEN)
RESP(WS-RESP)
END-EXEC
EXEC CICS WEB CLOSE
SESSTOKEN(WS-SESSION-TOKEN)
END-EXEC.
END-CALL.
EXIT.SOAP Web Services with WSDL
For SOAP-based web services, CICS uses a WEBSERVICE resource that links a WSDL definition to a CICS program. IBM's DFHWS2LS utility generates data structures from a WSDL and creates the binding between the SOAP envelope fields and COBOL data items — no manual XML parsing required.
The flow:
- Developer provides WSDL describing the service interface
DFHWS2LSgenerates COBOL copybooks and binding data- CICS WEBSERVICE, PIPELINE, and URIMAP resources are installed
- CICS handles SOAP envelope parsing automatically
- COBOL program uses EXEC CICS GET/PUT CONTAINER to access request/response data
Key Takeaways
CICS web services transform the mainframe from a 3270-only environment into a modern API platform. TCPIPSERVICE, URIMAP, and PIPELINE define the routing and message transformation layer. COBOL programs remain unchanged — they access HTTP request and response data through EXEC CICS GET/PUT CONTAINER on the predefined channel containers. This architecture allows organisations to expose decades-old, battle-tested COBOL business logic as JSON REST APIs callable by any modern client, without rewriting the logic. CICS also acts as a requester, enabling COBOL programs to consume external REST and SOAP APIs via EXEC CICS WEB commands.
For understanding how to define, install, and manage CICS resources in production, continue with CICS Resource Definitions. For the complete CICS course, visit the CICS Mastery Course
