Orchestrator
latest
false
Call modes explained - Automation Cloud latest
Banner background image
logo
Orchestrator User Guide
Last updated Feb 19, 2024

Call modes explained

API triggers call modes are specifically designed for creating and following job executions in Orchestrator.

The fundamental challenge with HTTP-based communication is that it is inherently synchronous: normally, the client sends a request and waits for the response from the server. However, in the context of robot jobs, keeping the connection open until the job has completed is not supported in Orchestrator.

To work around this, we’ve used the HTTP protocol to model multiple call modes. These modes rely on standard HTTP methods, status codes, and headers to create, monitor and get the result of jobs within the system, without unnecessarily keeping the connection open. Each of the proposed call modes has advantages and disadvantages, so you can choose the one that is best suited for your integration needs. Bear in mind that, to ensure secure communication, each call requires proper authentication through bearer tokens.

Important:

Known issue

Requests can sometimes be returned a 502 Bad Gateway Cloudflare error, caused by keeping a large number of connections alive for extended time intervals. The underlying job of such a request might have run despite the error, so you can check its state in Orchestrator.

This issue is intermittent, and any subsequent requests will work as expected.

Async polling

This call mode involves making a call with the preconfigured HTTP verb to trigger a new job and receive a status URI. The status URI must then be manually polled until the job completes. At this point, the call gets redirected to another endpoint, that is used to retrieve the job result (output or error).

Async polling workflow where the completion of the job depends on intermediate manual calls to the response location

docs image

The initial call is made using the configured HTTP verb (GET, POST, PUT, DELETE), which creates the associated job in Orchestrator. Upon successful job creation, the system responds with an HTTP status code 202 (Accepted) and a status URI in the Location header.

Once the job is created, you are expected to periodically poll its status. During this polling process, as long as the job is running, each GET request to the status URI returns an HTTP status code 200 (OK). When the job is completed, the next GET request to the status URI returns an HTTP status code 303 (See Other), redirecting to the output URI (via the Location header). You are expected to follow the output URI to retrieve the job result (output or error).

Always ensure to include a valid bearer token in the header of every call for successful authentication.

JavaScript example

This example illustrates how to start a job via an API trigger from a browser, using the async polling call mode.

const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));

const url = 'https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>';
const token = '<PERSONAL_ACCESS_TOKEN>'; // could also be an access token retrieved via OAuth

const body = {
  'argument1': 123,
  'argument2': 'my string',
  '$callMode': 'AsyncRequestReply' // optional argument to force call mode to AsyncRequestReply
}

// if invocation is done by GET, place the parameters in query string and remove the 'Content-Type' header
const invokeRequestOptions = {
  method: 'POST',
  headers: new Headers({ 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }),
  body: JSON.stringify(body),
};

const redirectRequestOptions = {
  method: "GET",
  credentials: 'same-origin',
  headers: new Headers({ Authorization: `Bearer ${token}` }),
  redirect: "follow", // this option must be set to follow, otherwise an 'opaqueredirect' response is returned
};

const response = await fetch(url, invokeRequestOptions);
let newLocation = response.headers.get("Location");

// first response should be 202 and have a location header
console.log(`Got ${response.status}, with location: ${newLocation}`);

for (let i = 0; i < 20; i++) {
  await sleep(SLEEP_DURATION);

  // follow the location header to the new endpoint
  const statusResponse = await fetch(newLocation, redirectRequestOptions);

  // if the response was redirected (and automatically followed), then the output endpoint has been reached
  // the output of the job can be found in the body of the response in JSON format
  if (statusResponse.status != 200 || statusResponse.redirected)
  {
    // read the job output
    const output = await statusResponse.json();
    console.log(`Got ${statusResponse.status}, with body: ${JSON.stringify(output)}`);

    break;
}const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));

const url = 'https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>';
const token = '<PERSONAL_ACCESS_TOKEN>'; // could also be an access token retrieved via OAuth

const body = {
  'argument1': 123,
  'argument2': 'my string',
  '$callMode': 'AsyncRequestReply' // optional argument to force call mode to AsyncRequestReply
}

// if invocation is done by GET, place the parameters in query string and remove the 'Content-Type' header
const invokeRequestOptions = {
  method: 'POST',
  headers: new Headers({ 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }),
  body: JSON.stringify(body),
};

const redirectRequestOptions = {
  method: "GET",
  credentials: 'same-origin',
  headers: new Headers({ Authorization: `Bearer ${token}` }),
  redirect: "follow", // this option must be set to follow, otherwise an 'opaqueredirect' response is returned
};

const response = await fetch(url, invokeRequestOptions);
let newLocation = response.headers.get("Location");

// first response should be 202 and have a location header
console.log(`Got ${response.status}, with location: ${newLocation}`);

for (let i = 0; i < 20; i++) {
  await sleep(SLEEP_DURATION);

  // follow the location header to the new endpoint
  const statusResponse = await fetch(newLocation, redirectRequestOptions);

  // if the response was redirected (and automatically followed), then the output endpoint has been reached
  // the output of the job can be found in the body of the response in JSON format
  if (statusResponse.status != 200 || statusResponse.redirected)
  {
    // read the job output
    const output = await statusResponse.json();
    console.log(`Got ${statusResponse.status}, with body: ${JSON.stringify(output)}`);

    break;
}

C# example

This example illustrates how to start a job via an API trigger from a C#-based application, using the async polling call mode.

public async Task<string> AsyncPollingExample()
{
    const string url = "https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>";
    const string token = "<PERSONAL_ACCESS_TOKEN>"; // could also be an access token retrieved via OAuth

    // create an http client that does not follow redirects and adds a bearer token on each call
    var httpClient = new HttpClient(new HttpClientHandler { AllowAutoRedirect = false });
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

    var arguments = new Dictionary<string, object>
    {
        { "argument1", 123 },
        { "argument2", "my string" },
        { "$callMode", "AsyncRequestReply" }, // optional argument to force call mode to AsyncRequestReply
    };

    var httpResponseStart = await httpClient.PostAsJsonAsync(url, arguments);
    var redirectUri = httpResponseStart.Headers.Location;

    if (httpResponseStart.StatusCode != HttpStatusCode.Accepted)
        throw new Exception("Could not invoke workflow");

    while (true)
    {
        var httpPollingResponse = await httpClient.GetAsync(redirectUri);

        if (httpPollingResponse.StatusCode == HttpStatusCode.Redirect)
        {
            var outputLocation = httpPollingResponse.Headers.Location;
            var outputResponse = await httpClient.GetAsync(outputLocation);
            var jobOutput = await outputResponse.Content.ReadAsStringAsync();

            return jobOutput;
        }

        await Task.Delay(1000);
    }
}public async Task<string> AsyncPollingExample()
{
    const string url = "https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>";
    const string token = "<PERSONAL_ACCESS_TOKEN>"; // could also be an access token retrieved via OAuth

    // create an http client that does not follow redirects and adds a bearer token on each call
    var httpClient = new HttpClient(new HttpClientHandler { AllowAutoRedirect = false });
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

    var arguments = new Dictionary<string, object>
    {
        { "argument1", 123 },
        { "argument2", "my string" },
        { "$callMode", "AsyncRequestReply" }, // optional argument to force call mode to AsyncRequestReply
    };

    var httpResponseStart = await httpClient.PostAsJsonAsync(url, arguments);
    var redirectUri = httpResponseStart.Headers.Location;

    if (httpResponseStart.StatusCode != HttpStatusCode.Accepted)
        throw new Exception("Could not invoke workflow");

    while (true)
    {
        var httpPollingResponse = await httpClient.GetAsync(redirectUri);

        if (httpPollingResponse.StatusCode == HttpStatusCode.Redirect)
        {
            var outputLocation = httpPollingResponse.Headers.Location;
            var outputResponse = await httpClient.GetAsync(outputLocation);
            var jobOutput = await outputResponse.Content.ReadAsStringAsync();

            return jobOutput;
        }

        await Task.Delay(1000);
    }
}

Async fire & forget

The fire and forget call mode returns a 200 OK status on successful job creation, without any other information about the job.

Async fire & forget workflow where the job is completed with no intermediate calls

docs image

JavaScript example

This example illustrates how to start a job via an API trigger from a browser, using the async fire & forget call mode.

const url = 'https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>';
const token = '<PERSONAL_ACCESS_TOKEN>'; // could also be an access token retrieved via OAuth
  
const body = {
  'argument1': 123,
  'argument2': 'my string',
  '$callMode': 'FireAndForget' // optional argument to force call mode to FireAndForget
}

const options = {
  method: 'POST',
  headers: new Headers({ 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }),
  body: JSON.stringify(body),
};

let response = await fetch(url, options);

console.log(`Got ${response.status}`);const url = 'https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>';
const token = '<PERSONAL_ACCESS_TOKEN>'; // could also be an access token retrieved via OAuth
  
const body = {
  'argument1': 123,
  'argument2': 'my string',
  '$callMode': 'FireAndForget' // optional argument to force call mode to FireAndForget
}

const options = {
  method: 'POST',
  headers: new Headers({ 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }),
  body: JSON.stringify(body),
};

let response = await fetch(url, options);

console.log(`Got ${response.status}`);

C# example

This example illustrates how to start a job via an API trigger from a C#-based application, using the async fire & forget call mode.

public async Task FireAndForgetExample()
{
    const string url = "https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>";
    const string token = "<PERSONAL_ACCESS_TOKEN>"; // could also be an access token retrieved via OAuth

    // create an http client that does not follow redirects and adds Bearer <token> on each call
    // if the follow redirects option is enabled, C# will not add a bearer token by default after the redirect
    var httpClient = new HttpClient(new HttpClientHandler { AllowAutoRedirect = false });
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

    var arguments = new Dictionary<string, object>
    {
        { "argument1", 123 },
        { "argument2", "my string" },
        { "$callMode", "FireAndForget" }, // optional argument to force call mode to LongPolling
    };

    var response = await httpClient.PostAsJsonAsync(url, arguments);

    Console.WriteLine(response.StatusCode);
}public async Task FireAndForgetExample()
{
    const string url = "https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>";
    const string token = "<PERSONAL_ACCESS_TOKEN>"; // could also be an access token retrieved via OAuth

    // create an http client that does not follow redirects and adds Bearer <token> on each call
    // if the follow redirects option is enabled, C# will not add a bearer token by default after the redirect
    var httpClient = new HttpClient(new HttpClientHandler { AllowAutoRedirect = false });
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

    var arguments = new Dictionary<string, object>
    {
        { "argument1", 123 },
        { "argument2", "my string" },
        { "$callMode", "FireAndForget" }, // optional argument to force call mode to LongPolling
    };

    var response = await httpClient.PostAsJsonAsync(url, arguments);

    Console.WriteLine(response.StatusCode);
}

Sync (long-polling)

This call mode involves an initial call that blocks and waits a while for the job to complete, followed by several possible blocking calls and redirections. Finally, upon job completion, the job result (output or error) is retrieved.

Depending on the tenant settings, authentication may be required for all calls or just the initial call.

Sync (long-polling) workflow where the result, be it successful or unsuccessful, is returned with the initial call

docs image

Sync (long-polling) workflow where several calls are automatically made towards job completion

docs image

The initial call is made using the configured HTTP verb (GET, POST, PUT, DELETE), which creates the associated job in Orchestrator. Upon successful job creation, the system blocks the current call while it waits for job completion. When the job completes, the blocked call is released, and a response including the job output arguments is sent back.

If after a timeout period the job has not yet completed, the system responds with an HTTP status code 303 (See Other), redirecting to the status URI (via the Location header). You are expected to follow the status URI, which is blocked until the job is completed. If the job is not completed after a timeout, you are yet again redirected to the status URI, thus creating a redirect loop. Upon successful completion of the job, the job result (output or error) is retrieved as part of the HTTP response.

By default, all calls need to include a valid bearer token for authorization. However, if the tenant settings option Require Authentication header for sync API Triggers redirects is not selected, only the initial call to the trigger requires the authentication header. Subsequent calls to the status endpoint can be made without an authorization header.

The maximum job duration for this call mode is 15 minutes.

JavaScript example

This example illustrates how to start a job via an API trigger from a browser, using the sync (long-polling) call mode.

const url = 'https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>';
const token = '<PERSONAL_ACCESS_TOKEN>'; // could also be an access token retrieved via OAuth

const body = {
  'argument1': 123,
  'argument2': 'my string',
  '$callMode': 'LongPolling' // optional argument to force call mode to LongPolling
}

const options = {
  method: 'POST',
  headers: new Headers({ 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }),
  body: JSON.stringify(body),
  redirect: "follow", // follow redirects automatically
};

let response = await fetch(url, options);
const output = await response.json();

console.log(`Got ${response.status} with body ${JSON.stringify(output)}`);const url = 'https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>';
const token = '<PERSONAL_ACCESS_TOKEN>'; // could also be an access token retrieved via OAuth

const body = {
  'argument1': 123,
  'argument2': 'my string',
  '$callMode': 'LongPolling' // optional argument to force call mode to LongPolling
}

const options = {
  method: 'POST',
  headers: new Headers({ 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }),
  body: JSON.stringify(body),
  redirect: "follow", // follow redirects automatically
};

let response = await fetch(url, options);
const output = await response.json();

console.log(`Got ${response.status} with body ${JSON.stringify(output)}`);

C# example

This example illustrates how to start a job via an API trigger from a C#-based application, using the sync (long-polling) call mode.

public async Task SyncExample()
{
    const string url = "https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>";
    const string token = "<PERSONAL_ACCESS_TOKEN>"; // could also be an access token retrieved via OAuth

    // create an http client that does not follow redirects and adds Bearer <token> on each call
    // if the follow redirects option is enabled, C# will not add a bearer token by default after the redirect
    var httpClient = new HttpClient(new HttpClientHandler { AllowAutoRedirect = false });
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

    var arguments = new Dictionary<string, object>
    {
        { "argument1", 123 },
        { "argument2", "my string" },
        { "$callMode", "LongPolling" }, // optional argument to force call mode to LongPolling
    };

    var response = await httpClient.PostAsJsonAsync(url, arguments);

    while(response.StatusCode == HttpStatusCode.Redirect)
    {
        // in case of redirection, keep following the latest location in the header
        var location = response.Headers.Location;
        response = await httpClient.GetAsync(location);
    }

    // read the job output/error from the last request
    var jobOutput = response.Content.ReadAsStringAsync();

    Console.WriteLine(jobOutput);
}public async Task SyncExample()
{
    const string url = "https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>";
    const string token = "<PERSONAL_ACCESS_TOKEN>"; // could also be an access token retrieved via OAuth

    // create an http client that does not follow redirects and adds Bearer <token> on each call
    // if the follow redirects option is enabled, C# will not add a bearer token by default after the redirect
    var httpClient = new HttpClient(new HttpClientHandler { AllowAutoRedirect = false });
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

    var arguments = new Dictionary<string, object>
    {
        { "argument1", 123 },
        { "argument2", "my string" },
        { "$callMode", "LongPolling" }, // optional argument to force call mode to LongPolling
    };

    var response = await httpClient.PostAsJsonAsync(url, arguments);

    while(response.StatusCode == HttpStatusCode.Redirect)
    {
        // in case of redirection, keep following the latest location in the header
        var location = response.Headers.Location;
        response = await httpClient.GetAsync(location);
    }

    // read the job output/error from the last request
    var jobOutput = response.Content.ReadAsStringAsync();

    Console.WriteLine(jobOutput);
}
  • Async polling
  • JavaScript example
  • C# example
  • Async fire & forget
  • JavaScript example
  • C# example
  • Sync (long-polling)
  • JavaScript example
  • C# example
Support and Services icon
Get The Help You Need
UiPath Academy icon
Learning RPA - Automation Courses
UiPath Forum icon
UiPath Community Forum
Uipath Logo White
Trust and Security
© 2005-2024 UiPath. All rights reserved.