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.
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.
Before writing any PeopleCode, think through the functional requirements for your outbound integration:
Request requirements:
Response requirements:
404 Not Found – sometimes an error, sometimes expected (e.g., “user doesn’t exist yet, create them”)408 Request Timeout – may be retried immediately429 Too Many Requests – rate limit hit, must wait and retryThere 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.
%IntBroker.ConnectorRequestThis 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.
%IntBroker.ProvideRestTestThis 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.
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:
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();
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();
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);
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();
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();
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);
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.
| 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) |
%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.%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.%IntBroker.ProvideRestTest is not officially documented by Oracle. It has been stable and widely used in the PeopleSoft community, but be aware that Oracle could change its behavior in a future PeopleTools release without notice.The PeopleTools integration broker does NOT support HTTP form post data (application/x-www-form-urlencoded) natively, but there are workarounds.
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);
%IntBroker.ConnectorRequest. It does not work with %IntBroker.ProvideRestTest because ProvideRestTest overrides the Content-Type back to XML. See the comparison table.application/x-www-form-urlencoded POST bodies. See MOS Doc ID 2187249.1 for Oracle’s enhancement request around broader custom Content-Type support.For a simpler approach that avoids this workaround, see the Apache HttpClient Form Post example in Method 3 above.
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.
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:
%IntBroker.SyncRequest approach is still appropriate when using delivered service operations (e.g., PERSON_BASIC_SYNC to an external node) or PeopleSoft-to-PeopleSoft integrations. For new custom integrations with external REST APIs, use one of the three methods above.Before PeopleSoft can make outbound HTTP requests, several infrastructure items need to be in place:
This is the most common source of headaches with outbound integrations. PeopleSoft cannot automatically connect to most HTTPS endpoints. Your PeopleSoft administrator must:
pskeymanager on the Integration Broker web serverSee 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.
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).
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.
Before writing any PeopleCode, use a tool like HTTPYac or Postman to:
This is a low-barrier way to iterate quickly without fighting the PeopleSoft framework.
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.
Use a configuration table to store:
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 every outbound API call to a custom table. Include:
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).
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.
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;
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.
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