🟢
Updated recently
Last updated:

Quick Answer: For ServiceNow REST SOAP integration Flow Designer work, the rule is simple — build outbound REST calls with a REST Message record and consume them from Flow Designer through IntegrationHub’s “Make a REST Call” action, and keep SOAP Message records only for legacy enterprise endpoints that still speak WSDL. Flow Designer is where orchestration, conditions and error handling belong; scripted calls inside business rules are the fallback for logic flows cannot express, not the default.

ServiceNow REST SOAP Integration Flow Designer: Choosing the Mechanism

ServiceNow gives you four ways to talk to the outside world, and choosing wrongly is what turns a two-week integration into a two-month one. The honest decision table:

Mechanism Use It When Avoid It When
REST Message + Flow Designer (IntegrationHub REST spoke) Modern JSON APIs, triggered by record events, needing conditions and logging You need complex data shaping Flow Designer actions cannot express cleanly
Scripted REST / sn_ws.RESTMessageV2 in a script Parsing logic, looping over payloads, or a script include used by several callers The flow could do it — you lose visibility and error handling for nothing
SOAP Message record Legacy enterprise endpoints — banking, ERP, government — that expose only WSDL The target has a JSON API; SOAP is heavier and slower to change
Import Set + Transform Map Bulk data in: files or feeds landing rows that need staging and coalesce logic You need a synchronous response back to the caller

One architectural rule that saves entire projects: never put a synchronous outbound call in a synchronous inbound path if you can avoid it. A REST call in an after business rule means the user’s save waits for someone else’s API, and someone else’s API will have a bad day. Prefer a flow triggered after commit, or an async pattern, so a slow partner degrades your reporting rather than your transaction.

Configuring a REST Message That Survives Production

A REST Message holds the endpoint, the methods, and the authentication. What you are aiming for is a record that a colleague can read six months later without opening your head: named method, clear variable substitutions, credentials in a proper credential record, and a timeout that fails fast rather than hanging a transaction.

The core configuration, in the shape you will actually fill it in:

REST Message : GetAssetFromSCM
  Endpoint   : https://api.scm.example.com/v2/assets
  Method     : GET  (name: getAsset)
  Authentication : OAuth 2.0 (client credentials), stored as a credential record
  Variable substitution : asset_tag  ->  {{asset_tag}}
  Timeout    : 20000 ms
  Additional parameters : Accept: application/json

And the calling script — a script include, so the logic has exactly one home:

function AssetClient() {}

AssetClient.prototype.getAsset = function (assetTag) {
    var msg = new sn_ws.RESTMessageV2('GetAssetFromSCM', 'getAsset');
    msg.setStringParameterNoEscape('asset_tag', assetTag);
    msg.setRequestHeader('Accept', 'application/json');
    msg.setTimeout(20000);

    var response = msg.execute();
    var status   = response.getStatusCode();

    if (status == 200) {
        return JSON.parse(response.getBody());
    }

    gs.warn('SCM lookup failed for ' + assetTag + ' :: HTTP ' + status
        + ' :: ' + msg.getErrorCode());
    return null;
};

Details that trip people up. setStringParameterNoEscape skips URL encoding — use plain setStringParameter unless you know the value is already encoded, and never pass raw user input into an encoded URL. Check the status code before parsing: a 401, a 429 and a 500 all arrive as a body, and parsing one blindly produces errors that look like your own bug. Log the getErrorCode() alongside the status, because “it returned null” is not a diagnosable message. And parse into a try/catch — a truncated JSON response from a partner under load is a routine occurrence, not an exotic one.

Putting the Call Inside Flow Designer

Flow Designer is where this becomes maintainable, because the trigger, the conditions, the call and the failure handling live in one visible object instead of three scripts. The build, step by step:

  1. Trigger. “When a record is created or updated” on your table, with a condition that narrows it — a state change, a flag, not “any update”. Unnarrowed triggers are how a flow ends up running thousands of times a day.
  2. Look-up or Get step. Pull the fields the integration needs in one step rather than referencing the trigger record repeatedly.
  3. Make a REST Call (IntegrationHub REST spoke). Select the REST message and method, map flow variables into the substitutions, and capture the response into a data pill you can inspect later.
  4. Conditional on the response. Branch on HTTP status. Success path updates the record; failure path writes the error into a field, creates a case, or logs to a custom table — the choice matters less than the fact that there is a path at all.
  5. Ask for it to run asynchronously where the option exists, so a slow partner endpoint does not sit inside the user’s transaction.

Debugging happens in the flow’s execution log (sys_flow_context), where each step shows inputs, outputs and the exact failure. That visibility is the real argument for Flow Designer over script: with a scripted call, the evidence lives in journal entries someone has to think to read. When you do drop into script, the query and transaction habits that keep those calls cheap are covered in the GlideRecord and server-side JavaScript guide.

When SOAP Is Still the Right Answer

In banking and large ERP estates, SOAP has not gone anywhere, and pretending otherwise costs you deals. The configuration mirrors REST — a SOAP Message record with the WSDL, endpoint and operation — and the call uses the sibling API:

var soap = new sn_ws.SOAPMessageV2('AssetSoap', 'getAssetByTag');
soap.setStringParameter('asset_tag', current.u_asset_tag);
soap.setTimeout(30000);

var resp  = soap.execute();
var http  = resp.getStatusCode();
if (http == 200) {
    var xml  = new XMLDocument2(resp.getBody());
    var node = xml.getFirstNode('//asset:status');
    current.u_sync_status = node.getNodeValue();
}

Expect three specific pains: XML namespaces that break when the vendor upgrades their WSDL without telling you, longer timeouts because the far end is an ESB that thinks in seconds, and heavier payloads over the wire. Budget for all three, and prefer a defensive parse that records “unexpected response shape” rather than throwing.

What Actually Happens at Work

A logistics company’s parts inventory needed nightly synchronisation with a supplier API. The developer built it correctly in every local sense: an after business rule that called the REST message for each updated item. In testing with a dozen items it ran fine. Then an import set landed 800 supplier price updates in one batch, and the rule dutifully made 800 outbound calls, serially, inside transactions that were already busy. The batch ran for hours, timed out repeatedly, and the price update that the business needed before the 9 AM stand-up was still running at 11.

There was no bug — the code did what it was told, which is exactly the problem. The fix was structural rather than clever: calls moved out of the rule entirely and into a flow triggered by the import’s completion, executing in small slices with a per-run ceiling, plus explicit handling for the 429 the supplier’s API started returning once we stopped abusing it. Retries were idempotent by design — the API call was keyed on a SKU and effective date, so a duplicate call updated rather than duplicated — because retry logic without idempotency is just a slower way to corrupt data.

The lesson the team kept: integrations do not fail in testing because the code is wrong; they fail in production because the volume is different. Ask “what happens when this runs 800 times in one batch?” before you ship, and your instance stays up on the days the business actually needs it. Config discipline around getting that change promoted safely sits in the update sets guide, and this exact skill — integration design under real volume — is the largest single lever in the ServiceNow developer salary guide.

Training Resources

Integrations are the highest-value ServiceNow skill to learn hands-on. SkilBrill ServiceNow Training covers REST and SOAP messaging, Flow Designer and IntegrationHub builds, error handling and real instance practice across the Developer track, with career support and placement assistance.

FAQ

How do I call a REST API from ServiceNow Flow Designer?

Define a REST Message with your endpoint and method, then use IntegrationHub’s “Make a REST Call” action in the flow, map flow variables into the substitutions, and branch on the returned HTTP status.

REST or SOAP for a ServiceNow integration?

REST for modern JSON APIs — it is simpler to configure, debug and test. SOAP only when the target system exposes a WSDL and nothing else, which is still common in banking, ERP and government systems.

Should ServiceNow integrations run in a business rule or Flow Designer?

Flow Designer by default: the trigger conditions, call and error handling are visible in one place with execution logs. Fall back to scripted calls in a script include when the payload logic is too complex for flow actions.

Why does my ServiceNow REST message time out in production but not in dev?

Volume, not code. A per-record call inside a business rule works on a handful of records and collapses on a bulk import. Move the calls into an async flow or job with a per-run ceiling, and handle rate-limit responses.

How should ServiceNow handle a failed outbound integration call?

Always branch on the HTTP status, write the error somewhere durable — a field, a case, a custom table — and make retries idempotent so a repeated call updates rather than duplicates. Silent failure is the worst option; an unhandled exception is second worst.