02-09-2022 11:09 AM
Hello all! Hope you are doing well.
I have been trying to retrieve my networking information from Postman, but I only get two networks out of the four when I run the GET. I'm able to access all the networks on the Meraki dashboard, but having no luck with APIs. I have created different API keys, but no luck. Any advice?
Solved! Go to Solution.
02-09-2022 02:15 PM
Then the queries would be simply :
https://api.meraki.com/api/v1/organizations/ ( with a valid API key )
https://api.meraki.com/api/v1/organizations/{organizationId}/networks ( with a valid Org ID obtained from the previous call )
Simply log into any Org that you have a API key in your browser and paste the urls in the url bar :
This is how I test my calls before scripting.
02-09-2022 12:02 PM
Could you precise what API call you using ?
02-09-2022 12:19 PM
GET {{baseUrl}}/organizations/
I got the organization ID from the Meraki Dashboard, but when I try to add it to the URL I get a 401.
02-09-2022 12:26 PM
So you are trying to Get https://api.meraki.com/api/v1/organizations/ which should return you a list of Orgs that you have access. Then you will be able to retrieve the ''id'' ( which is the OrgID ) and try https://api.meraki.com/api/v1/organizations/{organizationId}/networks with the correct ID.
My favorite way to test these API calls , is by using Chrome and logging to the desired Org and then typing the API url in the url bar.
02-09-2022 12:45 PM
Thanks for the advice. I am unsure how to test API calls from Chrome. Can you please provide a site that gives instructions?
And I have followed the correct steps to get the Organizations back. I noticed that the n# is different for the Organizations I am trying to access. I wonder if that is where the problem is.
02-09-2022 01:44 PM
No, I am not using v0. I am using v1. The GET request works for the networks that are on the same shard, but not the other two that are on different shards.
02-09-2022 02:06 PM
All networks from the same Org are on the same shard. Do not mix shards ID and Orgs.
That is why it is recommended to use the mega proxy api.meraki.com instead of the shard. If you really want to use the shard , you have to make sure that it is the right one.
02-09-2022 02:09 PM
I am using the mega proxy api.meraki.com.
I am only seeing the difference in the shard from the dashboard, so I wasn't sure if that was causing the issue. I have never used the shard in the API call.
02-09-2022 02:15 PM
Then the queries would be simply :
https://api.meraki.com/api/v1/organizations/ ( with a valid API key )
https://api.meraki.com/api/v1/organizations/{organizationId}/networks ( with a valid Org ID obtained from the previous call )
Simply log into any Org that you have a API key in your browser and paste the urls in the url bar :
This is how I test my calls before scripting.
02-09-2022 02:45 PM
Wow! That was awesome. Thanks for sharing that. I got the results and the Organization was present. However, when I add the organizationId( or the organizationId/networks) I get a 404 error.
I tested the method with the other networks and only one network returned with 200.
02-09-2022 02:49 PM
Has the Org API settings been enabled ? :
02-09-2022 02:52 PM
Yes, it has.
02-09-2022 02:59 PM
However, when I add the organizationId( or the organizationId/networks) I get a 404 error.
I tested the method with the other networks and only one network returned with 200.
I'm not sure I'm following you. The call https://api.meraki.com/api/v1/organizations/{organizationId}/networks It needs a OrgID not a NetworkID. You should be able to list all the networks from that given Org. If it still fails for the same Org , I would open a ticket.
02-09-2022 03:06 PM
It is working! Thank you!
01-31-2025 07:24 AM
Please direct me to the correct Group if this is incorrect.
After searching, this thread is the closest I have found to my issue.
I am using the Automation-scripts-Master Python Script for retrieving an inventory of each of my organizations networks but it has started to miss entire organizations. My API key is valid and I can pull the orgs missed if I use py inventorycvs.py -k <myapikey> -o "name" -f c:\temp\listofitems.csv
I get a list of the Org/networks/items but it is missing orgs.
import sys, getopt, requests, time, datetime, os, smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
from urllib.parse import urlencode
from requests import Session, utils
class NoRebuildAuthSession(Session):
def rebuild_auth(self, prepared_request, response):
"""Prevent auth header stripping on redirect."""
API_MAX_RETRIES = 3
API_CONNECT_TIMEOUT = 60
API_TRANSMIT_TIMEOUT = 60
API_STATUS_RATE_LIMIT = 429
API_RETRY_DEFAULT_WAIT = 3
FLAG_REQUEST_VERBOSE = True
API_BASE_URL = "https://api.meraki.com/api/v1"
API_KEY_ENV_VAR_NAME = "MERAKI_DASHBOARD_API_KEY"
def send_email(smtp_server, port, sender_email, sender_password, recipient_email, subject, body, attachment_path):
try:
msg = MIMEMultipart()
msg['From'] = sender_email
msg['To'] = recipient_email
msg['Subject'] = subject
msg.attach(MIMEText(body, 'plain'))
if attachment_path:
with open(attachment_path, "rb") as attachment:
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header(
"Content-Disposition",
f"attachment; filename={attachment_path.split('/')[-1]}",
)
msg.attach(part)
server = smtplib.SMTP(smtp_server, port)
server.starttls()
server.login(sender_email, sender_password)
server.send_message(msg)
server.quit()
print(f"Email sent successfully to {recipient_email}")
except Exception as e:
print(f"Failed to send email: {e}")
def merakiRequest(p_apiKey, p_httpVerb, p_endpoint, p_additionalHeaders=None, p_queryItems=None,
p_requestBody=None, p_verbose=False, p_retry=0):
if p_retry > API_MAX_RETRIES:
if(p_verbose):
print("ERROR: Reached max retries")
return False, None, None, None
bearerString = "Bearer " + str(p_apiKey)
headers = {"Authorization": bearerString}
if not p_additionalHeaders is None:
headers.update(p_additionalHeaders)
query = ""
if not p_queryItems is None:
qArrayFix = {}
for item in p_queryItems:
if isinstance(p_queryItems[item], list):
qArrayFix["%s[]" % item] = p_queryItems[item]
else:
qArrayFix[item] = p_queryItems[item]
query = "?" + urlencode(qArrayFix, True)
url = API_BASE_URL + p_endpoint + query
verb = p_httpVerb.upper()
session = NoRebuildAuthSession()
verbs = {
'DELETE' : { 'function': session.delete, 'hasBody': False },
'GET' : { 'function': session.get, 'hasBody': False },
'POST' : { 'function': session.post, 'hasBody': True },
'PUT' : { 'function': session.put, 'hasBody': True }
}
try:
if(p_verbose):
print(verb, url)
if verb in verbs:
if verbs[verb]['hasBody'] and not p_requestBody is None:
r = verbs[verb]['function'](
url,
headers = headers,
json = p_requestBody,
timeout = (API_CONNECT_TIMEOUT, API_TRANSMIT_TIMEOUT)
)
else:
r = verbs[verb]['function'](
url,
headers = headers,
timeout = (API_CONNECT_TIMEOUT, API_TRANSMIT_TIMEOUT)
)
else:
return False, None, None, None
except:
return False, None, None, None
if(p_verbose):
print(r.status_code)
success = r.status_code in range (200, 299)
errors = None
responseHeaders = None
responseBody = None
if r.status_code == API_STATUS_RATE_LIMIT:
retryInterval = API_RETRY_DEFAULT_WAIT
if "Retry-After" in r.headers:
retryInterval = r.headers["Retry-After"]
if "retry-after" in r.headers:
retryInterval = r.headers["retry-after"]
if(p_verbose):
print("INFO: Hit max request rate. Retrying %s after %s seconds" % (p_retry+1, retryInterval))
time.sleep(int(retryInterval))
success, errors, responseHeaders, responseBody = merakiRequest(p_apiKey, p_httpVerb, p_endpoint, p_additionalHeaders,
p_queryItems, p_requestBody, p_verbose, p_retry+1)
return success, errors, responseHeaders, responseBody
try:
rjson = r.json()
except:
rjson = None
if not rjson is None:
if "errors" in rjson:
errors = rjson["errors"]
if(p_verbose):
print(errors)
else:
responseBody = rjson
if "Link" in r.headers:
parsedLinks = utils.parse_header_links(r.headers["Link"])
for link in parsedLinks:
if link["rel"] == "next":
if(p_verbose):
print("Next page:", link["url"])
splitLink = link["url"].split("/api/v1")
success, errors, responseHeaders, nextBody = merakiRequest(p_apiKey, p_httpVerb, splitLink[1],
p_additionalHeaders=p_additionalHeaders,
p_requestBody=p_requestBody,
p_verbose=p_verbose)
if success:
if not responseBody is None:
responseBody = responseBody + nextBody
else:
responseBody = None
return success, errors, responseHeaders, responseBody
# Other functions here...
def main(argv):
arg_apikey = None
arg_orgname = "/all"
arg_file = None
arg_email = None # New email argument
try:
opts, args = getopt.getopt(argv, 'hk:o:f:e:')
except getopt.GetoptError:
print(readMe)
sys.exit()
for opt, arg in opts:
if opt == '-h':
print(readMe)
elif opt == '-k':
arg_apikey = arg
elif opt == '-o':
arg_orgname = arg
elif opt == '-f':
arg_file = arg
elif opt == '-e':
arg_email = arg
# Validate API key
apiKey = getApiKey(arg_apikey)
if apiKey is None:
print("Error: API key missing!")
sys.exit()
filepath = generateFileName() if arg_file is None else arg_file
# Generate CSV logic...
# Send email if email argument provided
if arg_email:
smtp_server = "smtp.office365.com"
port = 587
sender_email = "dwarren@clearlinktech.com"
sender_password = "There is no spoon."
subject = "Meraki Inventory CSV File"
body = f"Attached is the CSV file for {arg_orgname}."
send_email(smtp_server, port, sender_email, sender_password, arg_email, subject, body, filepath)I am curious if I am missing some recent changes or if my rate limiting is incorrect.
Thanks,
IronBones
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide