Contents

PeopleSoft as HTTP Client

This section covers using PeopleSoft to make outbound HTTP requests to third-party APIs. This is where PeopleSoft acts as the HTTP client and the external system is the HTTP server.

Overview

When PeopleSoft needs to call an external API (Salesforce, D2L, Workday, a custom microservice, etc.), the Integration Broker’s HttpTargetConnector handles the actual HTTP communication. Your PeopleCode runs on the Application Server (or Process Scheduler), which talks to the Integration Gateway on the Web Server, which then makes the outbound HTTP call.

Alternatively, you can bypass the Integration Broker entirely and use the Apache HttpClient Java library directly from PeopleCode. This approach makes HTTP calls directly from the Application Server without going through the Integration Gateway.

What You Need From an HTTP Client

Before writing any PeopleCode, think through the functional requirements for your outbound integration:

Request requirements:

  • Dynamically set the URL (hostname, path, query string parameters)
  • Dynamically set request headers (Content-Type, Accept, custom headers)
  • Dynamically set the request body (JSON, XML, or form data)
  • Dynamically set the HTTP method (GET, POST, PUT, DELETE)
  • Dynamically set authentication credentials (Basic Auth, Bearer tokens)

Response requirements:

  • Parse variable response data (JSON or XML)
  • React to HTTP status codes appropriately:
    • 404 Not Found – sometimes an error, sometimes expected (e.g., “user doesn’t exist yet, create them”)
    • 408 Request Timeout – may be retried immediately
    • 429 Too Many Requests – rate limit hit, must wait and retry
  • Read response headers (rate limit info, pagination, request IDs)

Three Methods for Outbound HTTP

There are three methods to make HTTP requests from PeopleCode. The first two use the Integration Broker and go through the Integration Gateway on the Web Server. The third bypasses the Integration Broker entirely.

Method 1: %IntBroker.ConnectorRequest

This is the standard, Oracle-documented method. It uses the IB_GENERIC_SYNC service operation and HttpTargetConnector directly.

Local Message &mRequest = CreateMessage(Operation.IB_GENERIC_SYNC);

&mRequest.IBInfo.IBConnectorInfo.ConnectorName = "HTTPTARGET";
&mRequest.IBInfo.IBConnectorInfo.ConnectorClassName = "HttpTargetConnector";

Local string &url = "https://api.example.com/employees";
Local boolean &bRet;

&bRet = &mRequest.IBInfo.IBConnectorInfo.AddConnectorProperties("URL", &url, %HttpProperty);
&bRet = &mRequest.IBInfo.IBConnectorInfo.AddConnectorProperties("Method", "POST", %HttpProperty);

/* Build JSON request body */
Local JsonObject &rootJSON = CreateJsonObject();
&rootJSON.AddProperty("name", "Jane Smith");
&rootJSON.AddProperty("email", "jane@example.com");

&bRet = &mRequest.SetContentString(&rootJSON.ToString());
&bRet = &mRequest.AddSegmentHeader("Content-Type", "application/json");
&bRet = &mRequest.AddSegmentHeader("Accept", "application/json");
&bRet = &mRequest.AddSegmentHeader("Authorization", "Basic dXNlcjpwYXNz");

Local Message &mResponse = %IntBroker.ConnectorRequest(&mRequest, True);

If &mResponse.ResponseStatus = %IB_Status_Success Then
   Local string &responseBody = &mResponse.GetContentString();
   /* Parse response JSON here */
Else
   /* Exception: &mResponse.IBException.ToString() */
End-If;

/* Read response headers */
Local string &name, &value;
For &i = 1 To &mResponse.IBInfo.IBConnectorInfo.GetNumberOfConnectorProperties()
   &name = &mResponse.IBInfo.IBConnectorInfo.GetConnectorPropertiesName(&i);
   &value = &mResponse.IBInfo.IBConnectorInfo.GetConnectorPropertiesValue(&i);
End-For;

Prerequisites: The IB_GENERIC_SYNC service operation and IB_GENERIC message must exist in your system. These are delivered by Oracle.

Method 2: %IntBroker.ProvideRestTest

This is a hidden, undocumented method used internally by the PeopleSoft REST test connector page. It uses the IB_GENERIC_REST_POST service operation.

Local Message &mRequest = CreateMessage(Operation.IB_GENERIC_REST_POST);

Local string &url = "https://api.example.com/employees";
&mRequest.OverrideURIResource(&url);

/* Build JSON request body */
Local JsonObject &rootJSON = CreateJsonObject();
&rootJSON.AddProperty("name", "Jane Smith");
&rootJSON.AddProperty("email", "jane@example.com");

Local boolean &bRet;
&bRet = &mRequest.SetContentString(&rootJSON.ToString());
&bRet = &mRequest.AddSegmentHeader("Content-Type", "application/json");
&bRet = &mRequest.AddSegmentHeader("Accept", "application/json");
&bRet = &mRequest.AddSegmentHeader("Authorization", "Basic dXNlcjpwYXNz");

Local Message &mResponse = %IntBroker.ProvideRestTest(&mRequest, "POST");

Local integer &statusCode = &mResponse.HTTPResponseCode;
Local string &responseBody = &mResponse.GetContentString();

/* Read response headers */
Local string &name, &value;
For &i = 1 To &mResponse.IBInfo.IBConnectorInfo.GetNumberOfConnectorProperties()
   &name = &mResponse.IBInfo.IBConnectorInfo.GetConnectorPropertiesName(&i);
   &value = &mResponse.IBInfo.IBConnectorInfo.GetConnectorPropertiesValue(&i);
End-For;

Prerequisites: The IB_GENERIC_REST_POST service operation and IB_GENERIC_REST message must exist in your system.

Method 3: Apache HttpClient (Bypass Integration Broker)

If you need to make HTTP calls from PeopleSoft that bypass the integration broker entirely, you can use the Apache HttpClient Java library directly from PeopleCode. This approach is useful when:

  • You need full access to HTTP response bodies on non-200 status codes (see Common REST Issues)
  • You need HTTP Form Post support without workarounds
  • You need simpler, more direct HTTP calls without IB overhead

HTTP GET

Local JavaObject &jHttp = CreateJavaObject("org.apache.commons.httpclient.HttpClient");
&jHttp.getHttpConnectionManager().getParams().setConnectionTimeout(20000);

Local string &sURL = "http://www.google.com";

Local JavaObject &jMethod = CreateJavaObject("org.apache.commons.httpclient.methods.GetMethod", &sURL);
&jMethod.setFollowRedirects( False);

&jHttp.executeMethod(&jMethod);

Local string &responseBody = &jMethod.getResponseBodyAsString();
Local integer &responseStatus = &jMethod.getStatusLine().getStatusCode();

HTTP POST of JSON

Local JavaObject &jHttp = CreateJavaObject("org.apache.commons.httpclient.HttpClient");
&jHttp.getHttpConnectionManager().getParams().setConnectionTimeout(20000);

Local string &sURL = "https://www.some-super-cool-webservice.com/api/v1/users";

Local JavaObject &jMethod = CreateJavaObject("org.apache.commons.httpclient.methods.PostMethod", &sURL);

&jMethod.setFollowRedirects( False);
&jMethod.setRequestHeader("Content-Type", "application/json");

Local string &jsonBody;
&jsonBody = GetHTMLText(HTML.MY_JSON_TEMPLATE);
&jMethod.setRequestBody(&jsonBody);

&jHttp.executeMethod(&jMethod);

Local string &responseBody = &jMethod.getResponseBodyAsString();
Local integer &responseStatus = &jMethod.getStatusLine().getStatusCode();

HTTP PUT and DELETE

For PUT, change the method class:

Local JavaObject &jMethod = CreateJavaObject("org.apache.commons.httpclient.methods.PutMethod", &sURL);

For DELETE:

Local JavaObject &jMethod = CreateJavaObject("org.apache.commons.httpclient.methods.DeleteMethod", &sURL);

HTTP Form Post

Local JavaObject &jHttp = CreateJavaObject("org.apache.commons.httpclient.HttpClient");
&jHttp.getHttpConnectionManager().getParams().setConnectionTimeout(10000);
&sURL = "http://some-host.com";

Local JavaObject &jMethod = CreateJavaObject("org.apache.commons.httpclient.methods.PostMethod", &sURL);

&jMethod.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

Local string &formData;
&formData = "formfield1=" | EncodeURLForQueryString("value1");
&formData = &formData | "&" | "formfield2=" | EncodeURLForQueryString("value2");

&jMethod.setRequestBody(&formData);

&jHttp.executeMethod(&jMethod);

Local string &responseBody = &jMethod.getResponseBodyAsString();
Local integer &responseStatus = &jMethod.getStatusLine().getStatusCode();

HTTP POST with Basic Auth

Local JavaObject &jHttp = CreateJavaObject("org.apache.commons.httpclient.HttpClient");
&jHttp.getHttpConnectionManager().getParams().setConnectionTimeout(20000);

Local string &sURL = "https://www.some-super-cool-webservice.com/api/v1/users";

Local JavaObject &jMethod = CreateJavaObject("org.apache.commons.httpclient.methods.PostMethod", &sURL);

&jMethod.setFollowRedirects( False);
&jMethod.setRequestHeader("Content-Type", "application/json");

/* Base 64 encode Basic Auth String */
Local object &crypto = CreateObject("Crypt");
&crypto.Open("BASE64_ENCRYPT");
&crypto.UpdateData("clear-text-basic-auth-key");  /* replace with your secret key */
Local string &Base64AuthHeader = &crypto.Result;
&Base64AuthHeader = Clean(&Base64AuthHeader); /* Crypto class adds carriage return at end */

&jMethod.setRequestHeader("Authorization", "Basic " | &Base64AuthHeader);

Local string &jsonBody;
&jsonBody = GetHTMLText(HTML.MY_JSON_TEMPLATE);
&jMethod.setRequestBody(&jsonBody);

&jHttp.executeMethod(&jMethod);

Local string &responseBody = &jMethod.getResponseBodyAsString();
Local integer &responseStatus = &jMethod.getStatusLine().getStatusCode();

HTTP GET of a Binary File

This example downloads a binary file (image, PDF, etc.) and saves it to the application server:

Local JavaObject &jHttp = CreateJavaObject("org.apache.commons.httpclient.HttpClient");
&jHttp.getHttpConnectionManager().getParams().setConnectionTimeout(20000);

Local JavaObject &jMethod = CreateJavaObject("org.apache.commons.httpclient.methods.GetMethod", &sURL);
&jMethod.setFollowRedirects( False);

&jHttp.executeMethod(&jMethod);

/* Get the response as a stream */
Local JavaObject &responseBody = &jMethod.getResponseBodyAsStream();

/* Convert Input Stream to Byte Array */
Local JavaObject &ioUtils = GetJavaClass("org.apache.commons.io.IOUtils");
Local JavaObject &byteArray = &ioUtils.toByteArray(&responseBody);

/* Write to file on app server */
Local JavaObject &out = CreateJavaObject("java.io.FileOutputStream", &TargetFullPath);
&out.write(&byteArray);

Get HTTP Response Headers

To pull a response header value:

Local string &customHeader;
&customHeader = &jMethod.getResponseHeader("x-custom").toString();

Prerequisites: The Apache HttpClient JAR files may or may not already be on your PeopleSoft servers. Check with your system administrator. If not present, download from the Apache HttpClient site.

Comparing the Three Methods

Feature ConnectorRequest ProvideRestTest Apache HttpClient
Documented by Oracle Yes No N/A (Java library)
Capture HTTP Status Codes No Yes Yes
4xx/5xx Behavior Cannot capture status codes; some errors return “success” Can get response code Full access to response body and status
Capture Response Headers Yes (on success) Yes (on success) Yes
Capture Response Cookies Yes No Yes
Framework-Injected Headers Datachunk, Datachunkcount, From, Messagename, Messagetype, Nonrepudiation, User-Agent User-Agent, Resttransaction=Y on POST None
Logged to MsgLog.html Yes (if log level set) Yes (if log level set) No (bypasses IB)
Logged to ErrorLog.html Yes No No (bypasses IB)
HTTP GET Yes Yes Yes
HTTP POST Yes Yes Yes
HTTP Form POST Yes (via SegmentContentType workaround) No (Content-Type gets overridden to XML) Yes (native)
HTTP DELETE Yes Yes Yes
JSON/XML Support Yes Yes Yes (manual)
Dynamic URLs, Paths, Query Strings Yes Yes Yes
Basic Auth / Bearer Token Yes Yes Yes
Requires Integration Gateway Yes Yes No (direct from App Server)

Which One Should You Use?

  • Use %IntBroker.ProvideRestTest for most modern REST API integrations because you can capture the HTTP response status code. Status codes are critical for proper error handling with modern APIs.
  • Use %IntBroker.ConnectorRequest if the API is sensitive to extra request headers (ProvideRestTest injects fewer), if you need to capture cookies, or if you are doing RPC/SOAP-style integrations where HTTP status codes are less important.
  • Use Apache HttpClient if you need full control over HTTP requests and responses without any IB overhead, if you need native form POST support, or if you need access to response bodies on non-200 status codes. The trade-off is that you lose all IB logging and monitoring.

HTTP Form Posts

The PeopleTools integration broker does NOT support HTTP form post data (application/x-www-form-urlencoded) natively, but there are workarounds.

Form POST via ConnectorRequest

The standard approach of setting the Content-Type header via AddConnectorProperties does not work for form data:

/* THIS DOES NOT WORK - PeopleSoft URL-encodes the entire body */
&bRet = &mRequest.IBInfo.IBConnectorInfo.AddConnectorProperties("Content-Type", "application/x-www-form-urlencoded", %Header);

When you do this, PeopleSoft URL-encodes the entire request body including the = and & delimiters. So key=value&key2=value2 becomes key%3Dvalue%26key2%3Dvalue2, which is mangled and unusable.

The workaround is to use SegmentContentType instead:

Local Message &mRequest = CreateMessage(Operation.IB_GENERIC_SYNC);

&mRequest.IBInfo.IBConnectorInfo.ConnectorName = "HTTPTARGET";
&mRequest.IBInfo.IBConnectorInfo.ConnectorClassName = "HttpTargetConnector";

Local boolean &bRet;
&bRet = &mRequest.IBInfo.IBConnectorInfo.AddConnectorProperties("URL", &url, %HttpProperty);
&bRet = &mRequest.IBInfo.IBConnectorInfo.AddConnectorProperties("Method", "POST", %HttpProperty);

/* Build the form body manually - only URL-encode the values, not the delimiters */
Local string &formBody;
&formBody = "grant_type=" | EncodeURLForQueryString("client_credentials");
&formBody = &formBody | "&client_id=" | EncodeURLForQueryString(&clientId);
&formBody = &formBody | "&client_secret=" | EncodeURLForQueryString(&clientSecret);

&bRet = &mRequest.SetContentString(&formBody);

/* This is the key - use SegmentContentType instead of AddConnectorProperties for Content-Type */
&mRequest.SegmentContentType = "application/x-www-form-urlencoded";

Local Message &mResponse = %IntBroker.ConnectorRequest(&mRequest, True);

For a simpler approach that avoids this workaround, see the Apache HttpClient Form Post example in Method 3 above.

Inbound Form POST

The integration broker cannot handle inbound HTTP form data. You can use an iScript for this. In the integration broker, your options are: header fields, query string fields, and XML/JSON post.

What About Traditional Service Operations?

You may be tempted to use the traditional approach of creating a full service operation with messages, nodes, and routings for outbound calls:

/* Traditional approach - NOT recommended for modern APIs */
Local Message &requestMessage = CreateMessage(Operation.MY_SERVICE);
&requestMessage.SetXmlDoc(&xdoc);
Local Message &responseMessage = %IntBroker.SyncRequest(&requestMessage);

This approach is generally not flexible enough for modern REST APIs because:

  • Too much configuration overhead (service operations, messages, nodes, routings)
  • No easy way to handle dynamic paths, query strings, and headers
  • APIs often return variable data that is hard to map to a predefined message schema
  • It may work 85% of the time but the other 15% is a pain

Technical Prerequisites

Before PeopleSoft can make outbound HTTP requests, several infrastructure items need to be in place:

Network Connectivity

  • Can the PeopleSoft Web Server (where the Integration Gateway runs) reach the external API?
  • DNS resolution must work from the web server
  • Egress firewall rules must allow outbound connections to the API host and port
  • Some APIs require IP whitelisting – provide your web server’s outbound IP to the vendor

TLS Certificates

This is the most common source of headaches with outbound integrations. PeopleSoft cannot automatically connect to most HTTPS endpoints. Your PeopleSoft administrator must:

  1. Import the external system’s TLS certificate chain using pskeymanager on the Integration Broker web server
  2. Reboot the web server after importing
  3. Re-import when certificates expire (which can be as often as every 90 days with Let’s Encrypt)

See Oracle Support Doc ID 658744.1 for the detailed procedure.

Also see the SNI Certificates section of the HttpTargetConnector page for a common gotcha with modern cloud-hosted APIs.

Credentials

  • Obtain API credentials (username/password, client ID/secret, API keys) from the vendor
  • Store credentials securely, not hardcoded in PeopleCode
  • Consider using a configuration table keyed by database name so DEV/TEST/PRD can have different credentials

Testing Connectivity

Use a Node Ping to verify that the Integration Broker can reach the external API. Set up a test node with the API’s base URL and click “Ping Node.” The ping performs an HTTP GET, so you need a URL that responds to GET with a 200 status code (many APIs have a /health or /ping endpoint).

Apache HttpClient JAR Files

For Method 3, the Apache HttpClient JAR files may or may not already be on your PeopleSoft servers. Check with your system administrator. If not present, download from the Apache HttpClient site and place them in the appropriate classpath on the Application Server.

Design Best Practices

Play With the API First

Before writing any PeopleCode, use a tool like HTTPYac or Postman to:

  • Understand the API’s endpoints, authentication, and data formats
  • Document all the HTTP transactions your integration needs
  • Discover edge cases and error responses
  • Build a collection of test requests you can reuse later

This is a low-barrier way to iterate quickly without fighting the PeopleSoft framework.

Use Application Package Classes

Wrap your HTTP client logic in PeopleCode Application Package classes. This separates the API complexity from your batch processes and pages.

The calling code should be simple:

import MY_INTEGRATION:api:UserService;

Local MY_INTEGRATION:api:UserService &svc;
&svc = create MY_INTEGRATION:api:UserService(&INSTITUTION, &EMPLID);

If &svc.CreateOrUpdateUser() Then
   /* Success */
Else
   /* Error: &svc.errorInfo */
End-If;

The class hides all the HTTP details: authentication, URL construction, JSON parsing, logging, retries, and environment-specific configuration.

Environment-Aware Configuration

Use a configuration table to store:

  • API base URL (different per environment: DEV/TEST/PRD)
  • Authentication credentials
  • Feature flags (logging level, dry-run mode)

Key the table by database name or institution so that a database refresh from PRD to DEV does not accidentally point your DEV system at production APIs.

Log API Interactions

Log every outbound API call to a custom table. Include:

  • Timestamp
  • HTTP method and URL
  • Request and response status code
  • Response time
  • Error messages (if any)

This is invaluable for production support, debugging edge cases, and detecting when a vendor changes their API behavior. It also gives you usage statistics (how many GETs vs POSTs, average response time, error rates).

Handling Responses

Parsing JSON Responses

Use the JsonObject and JsonArray classes to parse JSON responses:

Local string &responseBody = &mResponse.GetContentString();

Local JsonParser &parser = CreateJsonParser();
Local boolean &bRet = &parser.Parse(&responseBody);

If &bRet Then
   Local JsonObject &root = &parser.GetRootObject();
   Local string &name = &root.GetProperty("name").GetString();
   Local integer &id = &root.GetProperty("id").GetNumber();
End-If;

See the JSON Encoding and JSON Decoding sections for more detail.

Handling Status Codes

With ProvideRestTest, you get the actual HTTP status code:

Local integer &statusCode = &mResponse.HTTPResponseCode;

Evaluate &statusCode
When 200
When 201
   /* Success - parse response */
   Break;
When 404
   /* Not found - may or may not be an error in your workflow */
   Break;
When 401
   /* Authentication failed - check credentials */
   Break;
When 429
   /* Rate limited - wait and retry */
   Break;
When-Other
   /* Unexpected status - log and handle */
   Break;
End-Evaluate;

Rate Limiting

Many APIs enforce rate limits. If you hit a 429 Too Many Requests response, check the X-Rate-Limit-Reset or Retry-After response headers to know when you can retry. In batch processes, consider adding deliberate pauses between API calls to stay within limits.


Author Info
Chris Malek

Chris Malek s a PeopleTools® Technical Consultant with over two decades of experience working on PeopleSoft enterprise software projects. He is available for consulting engagements.

Work with Chris