Problem:
Many APIs limit the number of iterations that you can make in a single API call. For example, Brightpearl limits you to getting information for a maximum of 200 orders in a single API call. If you place a call with more than 200 orders, it will simply return an error message. SmartyStreets also places a limit of 100 addresses that you can validate with a single API call.
Solution:
Dave Wyatt at PowerShell.org provides the following solution.
Lets assume there is an array of 1000 addresses which are returned by convertfrom-csv. Here are the first couple of records from the original .csv file.
PS>cat lapsed.csv Addressee,first,spouse,Organization,Street,City,State,ZIP Joe Dokes,Joe, Mary,,,601 W 57TH St Apt 361,New York,NY,10019 Mary Smith ,Mary,Howard,,347 Poor Farm Rd,Colchester,VT,05446 Lu-Anne Jorden,Lu-Anne,Jess,,9603 North Kiowa Rd.,Parker,CO,80138
Here is the command that we use to read in the list into the variable $bigLlist
$bigList =(cat lapsed.csv | convertfrom-csv | Select-Object Addressee, Organization, Street, City, State, Zip )
$bigList is a custom object with the following layout:
PS>$biglist | get-member
TypeName: Selected.System.Management.Automation.PSCustomObject
Name MemberType Definition ---- ---------- ---------- Equals Method bool Equals(System.Object obj) GetHashCode Method int GetHashCode() GetType Method type GetType() ToString Method string ToString() Addressee NoteProperty System.String Addressee=Kamal Aboul-Hosn City NoteProperty System.String City=New York Organization NoteProperty System.String Organization= State NoteProperty System.String State=NY Street NoteProperty System.String Street=601 W 57TH St Apt 361 ZIP NoteProperty System.String ZIP=10019
If you look at this in Powershell, it prints out the contents of each record.
Addressee : Joe Dokes Organization : Street : 109 Fern Ct. City : Delray Beach State : FL ZIP : 33444 Addressee : Mary Smith Organization : Street : 205 Dorado Dr City : Cherry Hill State : NJ ZIP : 08034 Addressee : Lu-Anne Jorden Organization : Street : PO Box 81666 City : Fairbanks State : AK ZIP : 99708
Ok, so now we have the full list as an object. The list now needs to be subdivided into groups of 100.
$counter = @{ Value = 0 } $groupSize = 100 $groups = $bigList | Group-Object -Property { [math]::Floor($counter.Value++ / $groupSize) }
The $counter variable is a hash table, initialized to zero.
The $groupsize variable is the size of the individual group that can be sent. In our example it is set to 100, for a maximum of 100 addresses to be sent at a time.
The $groups variable creates a custom object, with the following members:
PS>$groups | gm TypeName: Microsoft.PowerShell.Commands.GroupInfo Name MemberType Definition ---- ---------- ---------- Equals Method bool Equals(System.Object obj) GetHashCode Method int GetHashCode() GetType Method type GetType() ToString Method string ToString() Count Property int Count {get;} Group Property System.Collections.ObjectModel.Collection[psobject] Group {get;} Name Property string Name {get;} Values Property System.Collections.ArrayList Values {get;}
If you print out the contents of $groups, you see the following list. (I’ve truncated for readability…)
PS>$groups Count Name Group ----- ---- ----- 100 0 {@{Addressee=Kamal Aboul-Hosn; Organization=; ... 100 1 {@{Addressee=Chandler Dawson; Organization=; ... 100 2 {@{Addressee=Sidsel Heney; Organization=; ... 100 3 {@{Addressee=John Marchetti; Organization=; ... 100 4 {@{Addressee=Jane Ramsey; Organization=; ... 59 5 {@{Addressee=James Tulloh; Organization=; ...
This shows that I have 559 names in the original file which has been divided up into 5 groups of 100 and one of 59 names.
The next and final step is to iterate through each group and make the API call.
foreach ($group in $groups) { $littleList = $group.Group | ConvertTo-Json $Output = Invoke-RestMethod -Uri $Uri -Body $littlelist -ContentType application/json -Method Post }
The steps are:
For each group
Convert the addresses in one group to JSON
Assign it to the variable $littlelist
Send the contents of $littlelist as the body of the API call.
End Loop.