Asynchronous request execution

Some REST API requests may initiate long-running processes. For example, if there is a business rule that triggers after creating a user, a request to create a user will return a response only after all actions of the business rule are executed.

If you anticipate that a request will take a long time to complete, you can execute it asynchronously. To do this, add the Adm-Wait HTTP header to your request and set the header value to the maximum number of seconds the API client will wait for synchronous execution. If the operation is not completed within the specified time, the server will return 202 Accepted status code and the operation identifier in the response body.

The operation identifier can then be used to query Adaxes about the operation status. To do this, make the following request:

GET ~/api/runningOperations/<operationId>

Request path parameters

  • Name

  • Required

  • Type

  • Description

  • operationId

  • True

  • string

  • The identifier of an asynchronous operation.

Request headers

  • Name

  • Required

  • Description

  • Adm-Authorization

  • True

  • Specify the security token obtained during authentication.

Request body

Do not send a body with this request.

Responses

If successful, returns 200 OK status code and an operation status in the response body. Otherwise, returns one of the common HTTP error codes and an error description in the response body.

Operation status is a JSON object with the following data structure:

{
    "completed": <true|false>,
    "operationResult": {
        "resultType": "<resultType>",
        "exception": null,
        "innerMessages": "<innerMessages>",
        "actualObjectDN": "<objectDN>",
        "extraInfo": "<extraInfo>"
    }
}

completed bool

Equals true if the operation has completed and false if not.


operationResult OperationResult

Contains the operation result if the operation has completed, or equals null if the operation is still running.


Example

 Create a user asynchronously

The following code sample creates a user. If user creation takes more than 5 seconds, it is executed asynchronously, and another request to check the operation status is made until the operation is completed.

PowerShell
$baseUrl = "https://host.example.com/restApi"
$requestHeaders = @{
    "Adm-Authorization" = YOUR-SECURITY-TOKEN;
    "Adm-Wait" = 5
}

# User creation request parameters
$endpoint = "/api/directoryObjects"
$requestUrl = $baseUrl + $endpoint
$requestBody = ConvertTo-Json -Depth 3 @{
    "createIn" = "CN=Users,DC=example,DC=com";
    "objectType" = "user";
    "properties" = @(
        @{
            "propertyName" = "cn";
            "propertyType" = 3;
            "values" = @("John Smith")
        },
        @{
            "propertyName" = "userPrincipalName";
            "propertyType" = 3;
            "values" = @("jsmith")
        }    
    )
}

# Create user
try
{
    $response = Invoke-WebRequest -Method POST -Headers $requestHeaders `
        -Uri $requestUrl -Body $requestBody -ContentType "application/json" `
        -ErrorAction Stop
}
catch
{
    Throw $_
}

# Check HTTP status code
switch ($response.StatusCode)
{
    # Operation completed synchronously in under 5 seconds
    200
    {
        # Get operation result
        $operationResult = $response.Content
        Write-Host $operationResult
    }
    # Wait time exceeded. Operation executes asynchronously
    202
    {
        # Get operation identifier
        $operationId = ConvertFrom-Json $response.Content

        # Query operation status until completed
        $endpoint = "/api/runningOperations/"
        $requestUrl = $baseUrl + $endpoint + $operationId
        $requestHeaders.Remove("Adm-Wait")
        do
        {
            $operationStatus = Invoke-RestMethod -Method GET `
                -Headers $requestHeaders -Uri $requestUrl
        }
        while (-not $operationStatus.Completed)  
        
        # Get operation result  
        $operationResult = $operationStatus.OperationResult
        Write-Host $operationResult
    }
    default
    {
        Write-Host "An error has occurred: " + $response.StatusCode
    }
}
C#
using System;
using System.Text;
using System.Text.Json;
using System.Net.Http;
using System.Threading.Tasks;

// Operation status data structure
public class OperationStatus
{
    public bool completed { get; set; }
    public object operationResult { get; set; }
}

class Program
{
    static async Task Main()
    {
        const string baseUrl = "https://host.example.com/restApi";

        // Specify user creation parameters
        string jsonRequest = @"
        {
            'createIn': 'CN=Users,DC=example,DC=com',
            'objectType': 'user',
            'properties': [
                {
                    'propertyName': 'cn',
                    'propertyType': 3,
                    'values': ['John Smith']
                },
                {
                    'propertyName': 'userPrincipalName',
                    'propertyType': 3,
                    'values': ['jsmith']                        
                }
            ]
        }";
        StringContent requestBody = new(jsonRequest, Encoding.UTF8, "application/json");

        // Initialize HTTP client
        using HttpClient client = new();
        client.DefaultRequestHeaders.Add("Adm-Authorization", YOUR-SECURITY-TOKEN);
        client.DefaultRequestHeaders.Add("Adm-Wait", "5");

        // Create user
        string endpoint = "/api/directoryObjects";
        HttpResponseMessage response = await client.PostAsync(
                baseUrl + endpoint, requestBody);
        string responseBody = response.Content.ReadAsStringAsync().Result;

        // Check HTTP status code
        switch (response.ReasonPhrase)
        {
            case "OK": // Operation completed synchronously in under 5 seconds
                // Get operation result
                Console.WriteLine(responseBody);
                break;

            case "Accepted": // Wait time exceeded. Operation executes asynchronously
                // Get operation identifier
                string operationId = JsonSerializer.Deserialize<string>(responseBody);

                // Query operation status until completed
                endpoint = "/api/runningOperations/";
                client.DefaultRequestHeaders.Remove("Adm-Wait");
                bool isCompleted;
                OperationStatus status;
                do
                {
                    responseBody = await client.GetStringAsync(baseUrl + endpoint + operationId);
                    status = JsonSerializer.Deserialize<OperationStatus>(responseBody);
                    isCompleted = status.completed;
                }
                while (!isCompleted);

                Console.WriteLine(responseBody);
                break;

            default: // An error has occurred
                Console.WriteLine("An error has occurred: " + response.StatusCode);
                break;
        }
    }
}

Responses

Create user

If the request to create a user is executed in under 5 seconds, the response body will contain the operation result.
HTTP Status code: 200 OK
Response body:

{
    "resultType": 0,
    "exception": null,
    "innerMessages": [],
    "actualObjectDN": "CN=John Smith,CN=Users,DC=example,DC=com",
    "extraInfo": {}
}

If the request to create a user takes more than 5 seconds to process, it will be executed asynchronously.
The response body will contain the operation identifier.
HTTP Status code: 202 Accepted
Response body:

"wghlm59rA8pDBgXA_tztCc0I"

Check operation status

The response body always contains the operation status. In the sample script, the operation status is checked until the operation is completed.
HTTP Status code: 200 OK
Response body:

{
    "completed": true,
    "operationResult": {
        "resultType": 0,
        "exception": null,
        "innerMessages": [],
        "actualObjectDN": "CN=John Smith,CN=Users,DC=example,DC=com",
        "extraInfo": {}
    }
}