Script to repeat PATCH commands to different URLS

Hi all,

I will admit I am very much a novice with using Postman and indeed any kind of API interface. I was content to explore and learn at my own pace, but some recent changes in our environment have forced my hand and escalated our timeline to ‘immediate urgency’.

The issue: I have 8000 users I have to manually update with 3 separate commands. I can chain these into a single PATCH no problem, however individually sending 8000+ requests is more than me or our team have the capacity for.

The command looks like this:

curl --request PATCH \
     --url https://api.smartrecruiters.com/user-api/v201804/users/USER1ID \
     --header 'accept: application/json' \
     --header 'content-type: application/json-patch+json' \
     --header 'x-smarttoken: REDACTED' \
     --data '
[
  {
    "op": "replace"
    "value": "[email protected]",
    "path": "/email",
  },
  {
    "op": "replace",
    "value": "PASSWORD",
    "path": "/ssoLoginMode"
  },
  {
    "op": "remove",
    "path": "/ssoIdentifier"
  }
]
'

What I need to do is basically create a script that is essentially:

curl --request PATCH \
     --url https://api.smartrecruiters.com/user-api/v201804/users/USER1ID \
     --header 'accept: application/json' \
     --header 'content-type: application/json-patch+json' \
     --header 'x-smarttoken: REDACTED' \
     --data '
[
  {
    "op": "replace"
    "value": "[email protected]",
    "path": "/email",
  },
  {
    "op": "replace",
    "value": "PASSWORD",
    "path": "/ssoLoginMode"
  },
  {
    "op": "remove",
    "path": "/ssoIdentifier"
  }
]
'
curl --request PATCH \
     --url https://api.smartrecruiters.com/user-api/v201804/users/USER2ID \
     --header 'accept: application/json' \
     --header 'content-type: application/json-patch+json' \
     --header 'x-smarttoken: REDACTED' \
     --data '
[
  {
    "op": "replace"
    "value": "[email protected]",
    "path": "/email",
  },
  {
    "op": "replace",
    "value": "PASSWORD",
    "path": "/ssoLoginMode"
  },
  {
    "op": "remove",
    "path": "/ssoIdentifier"
  }
]
'
curl --request PATCH \
     --url https://api.smartrecruiters.com/user-api/v201804/users/USER3ID \
     --header 'accept: application/json' \
     --header 'content-type: application/json-patch+json' \
     --header 'x-smarttoken: REDACTED' \
     --data '
[
  {
    "op": "replace"
    "value": "[email protected]",
    "path": "/email",
  },
  {
    "op": "replace",
    "value": "PASSWORD",
    "path": "/ssoLoginMode"
  },
  {
    "op": "remove",
    "path": "/ssoIdentifier"
  }
]
'

Repeat etc for 500 users at a time (or 200 - either way, its easier than 1 at a time). I had a look at flows, but I lack the expertise to know whether or not this is the correct approach. TBH I was hoping to use my massive excel spreadsheet to create the ‘script’ componants for each user, then just copy paste the script chunks as above, but I don’t know whether I can use multiple URLs in the same call?

I appreciate any insight you can provide as I am very much a novice here.

You can copy and paste that cURL command into Postman and it will generate a GUI request.

There are a couple of mistakes in that cURL command (extra comma’s) that may work in cURL but will show as errors in Postman.

The request should eventually look like this.

You would parameterize the elements that will change on each iteration.

For example the values.

You can then use a CSV file (or JSON if you prefer) as a data file in the Collection Runner.

https://blog.postman.com/using-csv-and-json-files-in-the-postman-collection-runner

This will run your collection or folder once for each line in the data file.

I would break the CSV file down into smaller chunks.

1 request while you test in, then 10 requests, then 100 before running in chunks of 1000.

It can probably run all 8000 in one go, but I would still probably break it down into smaller runs.

1 Like

That’s brilliant! Thank you so much! I did catch the comma issues once I posted the copied text into postman. I was working off the gui.

My main issue is that the url itself also changes. UserID is tacked into the url which I could also parameterise into the csv bit I’m not sure how to reflect this? I assume the url would be something like https://api.smartrecruiters.etc…/etc/users/{{UserID}}? Which would be perfect.

You can parameterize the whole URL, or just part of it.

image

Or by using a Path Variable which would look like this in the GUI.

1 Like

That’s so helpful thank you. :slight_smile:

So I followed your advice and I’m getting a variety of 4xx errors - 404, 415 and 400. Which tells me I’ve done something wrong but can’t quite work out what.

The csv file looks like this:

The call looks like this:

But when I run it, I just get errors. I’ve tried adding the “ “ to the email addresses in the csv, I’ve tried using srID as a param not a path param. the headers look normal:

But when I run the request, I get ‘User not found’:

I feel like the param on the end of the URL might be throwing things? But I can’t remove it from the parameter list or nothing happens? I am obviously missing something but can’t for the life of me work it out. Any thoughts?

Your original cURL is just using a JSON body. No query parameters. Your latest screenshots have a JSON body, a path variable and a query parameter. Looks like it’s all a bit mixed up. Remove the query parameter and the path variable and just parameterize the user id path by entering the variable directly into the URL like the first screenshot I posted.

Is the userid the same as the email. It didn’t look the same in your example. The example wasn’t showing the srID either.

So the body is pulled directly from the smartrecruiters api interface. I didn’t do anything new to it. It seems to have a mind of it’s own because it was missing commas yesterday.

The userid/srid are the same thing, I just renamed it to match the column header in my user export spreadsheet.

So the url uses the srid to identify the user record, the email address is a different variable. I need to update the email address for every unique userid/srid (which is just short for smartrecruitersid). I can’t give you a real world example but basically I have a user record:

Srid: 12345etc

Email: [email protected]

Ssoidentifier: [email protected] (they can be different from the email address in some cases due to quirks in the domain)

Ssologinmode: sso

Firstname: user

Lastname: userton etc etc

The api url uses the srid as the end of it’s address (as you’d expect) and so I tried it both as a path param and a variable and didn’t have much joy either way around because as soon as I defined the {{email}} variable, I started getting 404 errors.

The edit I need to make to the record is to change their address to [email protected], change their SSO login mode from sso to password (they are different authentication types) with a replace operator , and to remove the old SSO identifier variable with the remove operator.

I need to do this 8000 times so ideally I’d love to use the collection runner as this would save me a significant amount of work and budget. I followed the advice from your previous post and I feel like I’m almost there, but there is one tiny thing missing. If it helps, the SmartRecruiters api interface does have other formats available - java script, c, powershell, python too I think. There are a few different ones so maybe the json/cURL thing is throwing it off?

Can you get a single request to work via cURL?

Your original example, did not have the Srid in the URL (or in the body).

It just had the userID at the end of the path.

On face value, it just looks like you need to parameterize that userID in the URL, and email value in the JSON body.

The userid that you had in the URL wasn’t an email address.

Are we saying that the srID is the userID?

Let’s look at that example again…

curl --request PATCH \
     --url https://api.smartrecruiters.com/user-api/v201804/users/USER1ID \
     --header 'accept: application/json' \
     --header 'content-type: application/json-patch+json' \
     --header 'x-smarttoken: REDACTED' \
     --data '
[
  {
    "op": "replace"
    "value": "[email protected]",
    "path": "/email",
  },
  {
    "op": "replace",
    "value": "PASSWORD",
    "path": "/ssoLoginMode"
  },
  {
    "op": "remove",
    "path": "/ssoIdentifier"
  }
]

Do you have documentation for this API which defines the patch request? That is usually the first place to look when you are having issues crafting a particular request.

Based on the information to hand, I think the request needs to look like the following. (No query parameters or path variables).

Final piece of advice is to check the console logs to see if the information from your data file is being transposed correctly.

1 Like

Yes. A single defined request does work, although running it via postman does require that I manually update the content type to application/json-patch+json every time

The ui provided by the supplier is this: Update a user

I can get a single request to work. The USER1ID in my original example was meant to represent the srID.

So an actual request for a test user in the above interface looks like this (token redacted). The SRID is the bit at the end of the request URL. 6880f71efce6d4bde0a66bbd is the srID/userID/unique identifier every user has a different one.

curl --request PATCH \
     --url https://api.smartrecruiters.com/user-api/v201804/users/6880f71efce6d4bde0a66bbd \
     --header 'accept: application/json' \
     --header 'content-type: application/json-patch+json' \
     --header 'x-smarttoken: REDACTED' \
     --data '
[
  {
    "op": "remove",
    "path": "/ssoidentifier" - this just clears the ssoidentifier value in the record
  },
  {
    "op": "replace",
    "value": "PASSWORD", - This is an authentication type, not a pw and needs to be changed for this project to work
    "path": "/ssoLoginMode"
  },
  {
    "op": "replace",
    "value": "[email protected]"
    "path": "/email"
  }
]
'

I did notice that when I put the {{email}} into the params field, it added it to the url: https://api.smartrecruiters.com/user-api/v201804/users/:srID?email={{email}} I can’t seem to avoid that, so the url never looks like it does in your example.

Why are you putting the email in as a query parameter?

You need to add it to the body.

{
    "op": "replace",
    "value": {{email}},
    "path": "/email"
}
1 Like

Thank you so much for all your input and the time you’ve spent helping me. I did get a weird error until I tweaked the run order of the instructions (don’t ask me why, but if it works I’m not going to question it). I managed to get a successful run on the command for 22 test users. I’m just awaiting feedback from them as to whether they are able to access their accounts via the new email addresses, and then I can proceed with the migration.

1 Like