POST /api/source/loadAccounts

Hi Mark, I had something similar with my Okta source, where I needed to turn off delta aggregations before performing my unoptimised aggregation.

@colin_mckibben is this expected behaviour with the /beta import-accounts endpoint? If delta aggregations are on it will attempt an unoptimised delta aggregation?

It would be a really nice feature to have a flag in this API to trigger full or delta aggregations on command, for testing/troubleshooting purposes.

You could try something like the following to workaround the current limitations. I have not been able to fully test this yet. As soon as I went to test the tenant went down. So you might have to modify it a little bit. Please let me know if you need any help with this.

Python Code:

import requests

def getBearerToken(clientId, clientSecret, baseUrl):
    token = requests.post(baseUrl + "/oauth/token?grant_type=client_credentials&client_id=" + clientId + "&client_secret=" + clientSecret)
    return token

sourceId = "{{SOURCEID FROM IDN}}"
tenant = "{{tenant Name}}"
apiUrl = "https://" + tenant + ".api.identitynow.com/beta/sources/" + sourceId + "/load-accounts"
form_data = {"disableOptimization": "true"}

#Get the bearer token that will passed when making other api calls
baseUrl = "https://" + tenant + ".api.identitynow.com"
clientId = "{{CLIENTID}}"
clientSec = "{{CLIENTSECERT}}"

#Get the access token to use laster on.
token = getBearerToken(clientId, clientSec, baseUrl)

#Convert the repsonse object in a json objet
jsontoken = token.json()

#Put the access token into a variable for later use
bearerToken = jsontoken['access_token']

headers = {
    'Content-Type': 'multipart/form-data',
    'Accept': 'application/json',
    'Authorization': 'Bearer ' + bearerToken
}

response = requests.post(apiUrl, headers=headers, data=form_data)

if response.status_code == 200:
    response
else:
    print("Request Failed")

Thank you I will give that a go and see if that addresses not pulling in any accounts.

Howdy everyone - we were able to get the load-accounts (/beta/sources/{id}/load-accounts) working through a power automate schedule.

We needed to have the header value
Content-Type: multipart/form-data

But the key factor was actually the body - we had to formulate is like so to work correctly.

{
  "$content-type": "multipart/form-data",
  "$multipart": [
    {
      "headers": {
        "Content-Disposition": "form-data; name=\"disableOptimization\""
      },
      "body": "true"
    }
  ]
}
3 Likes

For some reason the python use is returning a 500 error message. And this is even after building the request using the built in code from the API docs page.

And no luck I have tried to pass in the information a few ways.

"https://" + tenant + ".api.identitynow.com/beta/sources/" + sourceId + "/load-accounts?disableOptimization='true'"
form_data = {}
files = []

What the API docs said should be run:

import requests

url = "https://" + tenant + ".api.identitynow.com/beta/sources/" + sourceId + "/load-accounts"

payload={}
files=[

]
headers = {
  'Content-Type': 'multipart/form-data',
  'Accept': 'application/json',
  'Authorization': 'Bearer ' + bearerToken
}

response = requests.request("POST", url, headers=headers, data=payload, files=files)

print(response.text)

Response:

'{"messages":[{"localeOrigin":"DEFAULT","text":"An internal fault occurred.","locale":"en-US"},{"localeOrigin":"REQUEST","text":"An internal fault occurred.","locale":"en-US"}],"trackingId":"d60cf352ebc64b179facdaca3047eb76","detailCode":"500.0 Internal fault"}'

The API specs don’t do a good job of generating example payloads for multipart form data. Try this.

import requests

url = "https://" + tenant + ".api.identitynow.com/beta/sources/" + sourceId + "/load-accounts"

files=[]
data={
  "disableOptimization": True
}

headers = {
  'Content-Type': 'multipart/form-data',
  'Accept': 'application/json',
  'Authorization': 'Bearer ' + bearerToken
}

response = requests.request("POST", url, headers=headers, data=data, files=files)

print(response.text)

Here is the output I got:

{"messages":[{"localeOrigin":"DEFAULT","text":"An internal fault occurred.","locale":"en-US"},{"localeOrigin":"REQUEST","text":"An internal fault occurred.","locale":"en-US"}],"detailCode":"500.0 Internal fault","trackingId":"04f9cc055f694dd7bf4416b5c50bc834"}

Full Request:

import requests

url = "https://" + tenant + ".api.identitynow.com/beta/sources/" + sourceId + "/load-accounts"

payload={
    "disableOptimization": True
}
files=[

]
headers = {
  'Content-Type': 'multipart/form-data',
  'Accept': 'application/json',
  'Authorization': 'Bearer ' +  bearerToken
}

response = requests.request("POST", url, headers=headers, data=payload, files=files)

print(response.text)

I ran this operation in postman and then used the code generator in postman to produce a viable Python request. It looks like form-data payloads have to either be text or a file. Booleans don’t seem to be supported. Try this.

import requests

url = "https://tenant.api.identitynow.com/beta/sources/b569e8001537420bb5521f83c2e3119f/load-accounts"

payload = {'disableOptimization': 'true'}
files=[

]
headers = {
  'Content-Type': 'multipart/form-data',
  'Authorization': 'Bearer <your-token>'
}

response = requests.request("POST", url, headers=headers, data=payload, files=files)

print(response.text)

@colin_mckibben Thank you I forgot that existed in postman. I will give it a try and see what comes of it.

@mpotti If interested you can do this with our python SDK as well with the snippet below. The accounts.csv here is just a file in the same directory in the script.

import sailpoint
import sailpoint.beta
from sailpoint.configuration import Configuration

configuration = Configuration()

# # Enter a context with an instance of the API client
with sailpoint.beta.ApiClient(configuration) as api_client:

    response = sailpoint.beta.SourcesApi(api_client).import_accounts(id='2c91808684149198018415574b9b15f4', file='accounts.csv', disable_optimization=True)

# Without file
# response = sailpoint.beta.SourcesApi(api_client).import_accounts(id='2c91808684149198018415574b9b15f4', disable_optimization=True)
    print(response)
2 Likes

There seems to be an issue with the Python requests library when setting Content-Type to ‘multipart/form-data’ that is causing the internal fault error. Content-Type is automatically set correctly by the files parameter, so you can utilize that for an unoptimized aggregation even if you are aggregating a direct connected source.

import requests

headers = {
# requests won't add a boundary if this header is set when you pass files=
# 'Content-Type': 'multipart/form-data',
'Authorization': 'Bearer <token>'
}

files = {
'disableOptimization': (None, 'true'),
}

response = requests.post(
'https://<org>.identitynow.com/beta/sources/<sourceid>/load-accounts',
headers=headers,
files=files,
)
1 Like

Hello Neil,
Any update about “system” user reported during the aggregation and not the real user ?
Thank you,

Furthermore, I note that if we wish to launch an aggregation while one is already present, the API returns an error message but with a code 202: a bit treacherous if the first test of good execution is carried out on the code of returns and forces you to parse the response looking for the specific text (which is likely to change without warning since it seems minor).
When do you think ? Does this type of error merit returning a 4XX?

I think you’re right. This API should return a 4xx when it encounters a currently running provisioning. Can you please submit a Bugs with the details of your findings?

1 Like

I had also raised this same concern in the past as well @colin_mckibben. Let’s bring it up again. :slight_smile:

According to the communications I saw, it should be fixed and released now. Can you give it a go on your side?

1 Like

@neil_mcglennon
Has this been deprciated in ap-southeast-2 by mistake - I know it happened in our Sandbox environment last month(seems to have been reverted) but we are seeing issues in Prod

From our prod this morning :

Was there a ticket already opened internally that you can re-launch or do you want me to open a bug ?

If you are seeing production issues, please open a support ticket to get a more timely response.

Any insight on when unoptimized aggregation will be supported with the new endpoint? I just tried and can’t trigger an unoptimized. Actually, I get a 500 error when adding “Content-Type” : “multipart/form-data” and “Accept” : “application/json” but it runs an optimized aggregation fine without these headers.