here is my python code
import requests
from boxsdk import Client, OAuth2
CLIENT_ID = '***************'
CLIENT_SECRET = '*************'
AUTHORIZATION_URL = 'https://api.box.com/oauth2/token'
# Define the payload for the authentication request
payload = {
'grant_type': 'client_credentials',
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'box_subject_type': 'enterprise', # Add the appropriate subject type here,
'box_subject_id':'444444'
}
# Make a POST request to the authorization URL with the headers
response = requests.post(AUTHORIZATION_URL, data=payload)
# Extract the access token from the response
if response.status_code == 200:
access_token = response.json()['access_token']
print(f'Access Token: {access_token}')
else:
print(f'Failed to retrieve access token. Status code: {response.status_code}, Error: {response.text}')
BOX_ACCESS_TOKEN = access_token
# # Define your folder ID
FOLDER_ID = "232374452899"
# Make a request to the Box API to get the list of items in the folder
response = requests.get(
f"https://api.box.com/2.0/folders/{FOLDER_ID}/items?sort=date&limit=1&direction=DESC",
headers={"Authorization": f"Bearer {BOX_ACCESS_TOKEN}"}
)
print(response.json())
Hi @DCuser122 , welcome to the forum!
Most likely the service account associated with the CCG authentication, does not have access to the folder.
Have you tried the as-user
option and pass the user id of the folder owner?
The are several options to solve this, let us know your use case.
Cheers
Thank you @rbarbosa !
I tried this but i get the same error. I’m a collaborator to the app.
# Define the user ID for the 'As-User' header
user_id = '29554489963'
# Define the headers including the 'As-User' header
headers = {
'as-user': user_id
}
# Make a POST request to the authorization URL with the headers
response = requests.post(AUTHORIZATION_URL, data=payload, headers=headers)
# Extract the access token from the response
if response.status_code == 200:
access_token = response.json()('access_token']
print(f'Access Token: {access_token}')
else:
print(f'Failed to retrieve access token. Status code: {response.status_code}, Error: {response.text}')
@rbarbosa my use case is
we have a enterprise box account and need to download most recent excel file from a folder every week.
To do this, I have created a custom app “OAuth 2.0 with Client Credentials Grant (Server Authentication)” setting and added my account a collaborator.
Please let me if you need any other details.
Looking forward to your response to fix this problem.
thanks!
Hi @DCuser122
Let me try to illustrate what I mean by permission issue.
As a user I’ve created a folder and put some files in there:
Notice the url with the folder id.
Now consider this python script:
"""sample to illustrate service account access to box content"""
import logging
from boxsdk import CCGAuth, Client
from boxsdk.exception import BoxAPIException
logging.basicConfig(level=logging.INFO)
logging.getLogger("boxsdk").setLevel(logging.CRITICAL)
CLIENT_ID = "h5...qi"
CLIENT_SECRET = "Tq...8"
ENTERPRISE_ID = "877840855"
USER_ID = "18622116055"
FOLDER_ID = "232513398018"
def get_box_client(user_id: str = None, enterprise_id: str = ENTERPRISE_ID):
"""get a box client with a service account"""
auth = CCGAuth(client_id=CLIENT_ID, client_secret=CLIENT_SECRET, user=user_id, enterprise_id=enterprise_id)
client = Client(auth)
return client
def folder_content(client: Client, folder_id: str = "0"):
"""get folder content"""
try:
folder = client.folder(folder_id=folder_id).get()
except BoxAPIException as e:
if e.status == 404:
print(f"Folder {folder_id} not found\n")
return
print(f"Items in: {folder.name} {folder.id}")
print("-" * 80)
items = folder.get_items()
for item in items:
print(f"{item.type} {item.name} {item.id}")
print("-" * 80 + "\n")
def main():
# service account
client = get_box_client(None)
me = client.user().get()
print(f"Service account: {me.name} {me.id}")
folder_content(client)
print(f"Service account: {me.name} {me.id}")
folder_content(client, FOLDER_ID)
# as-user
user = client.user(USER_ID).get()
as_user_client = client.as_user(user)
me = as_user_client.user().get()
print(f"As-User account: {me.name} {me.id}")
folder_content(as_user_client, FOLDER_ID)
if __name__ == "__main__":
main()
Note that USER_ID = "18622116055"
is the owner of the folder, in this case me.
Now if you run this script it results in:
Service account: CCG 20706451735
Items in: All Files 0
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
Service account: CCG 20706451735
Folder 232513398018 not found
As-User account: Rui Barbosa 18622116055
Items in: Folder to store files 232513398018
--------------------------------------------------------------------------------
file Sample A.docx 1345101805458
file Sample B.xlsx 1345083652268
--------------------------------------------------------------------------------
Service account CCG has no files or folders shared (collaborated) with it. Listing the root folder FOLDER_ID=0
shows an empty list.
As expected listing FOLDER_ID = "232513398018"
returns a 404 not found.
However, and still using the CCG enterprise client, I point the as-user
to the owner of the folder, int this case USER_ID = "18622116055"
I can list the folder content.
# as-user
user = client.user(USER_ID).get()
as_user_client = client.as_user(user)
me = as_user_client.user().get()
print(f"As-User account: {me.name} {me.id}")
folder_content(as_user_client, FOLDER_ID)
Resulting in:
As-User account: Rui Barbosa 18622116055
Items in: Folder to store files 232513398018
--------------------------------------------------------------------------------
file Sample A.docx 1345101805458
file Sample B.xlsx 1345083652268
--------------------------------------------------------------------------------
To do this you need to have your CCG app configured as follows:
App Access Level: App+Enterprise Access
Application Scopes: At least Manage users
Advanced Features: Make API calls using the as-user header
If you make changes to these remember to reauthorize your app, so changes take effect:
And then approve them in the admin console:
Let us know if this solves the issue.
Cheers
@rbarbosa Thank you so much! It worked.
The problem was I didn’t submit the app for re-auth for authorization. After reauth it worked.
I have another question, how do i get last modified file from your code.
def folder_content(client: Client, folder_id: str = "0"):
"""get folder content"""
try:
folder = client.folder(folder_id=folder_id).get()
except BoxAPIException as e:
if e.status == 404:
print(f"Folder {folder_id} not found\n")
return
print(f"Items in: {folder.name} {folder.id}")
print("-" * 80)
items = folder.get_items()
for item in items:
print(f"{item.type} {item.name} {item.id}")
print("-" * 80 + "\n")
@DCuser122
The folder.get_items
returns few details and several object types, like file
, folder
, and weblink
So we have to do this in 3 steps:
- From the items grab only files
- For each item representing a file, grab the details, which includes the modified at
- Sort that list
Consider this method:
def files_in_folder(client: Client, folder_id: str = "0"):
try:
folder = client.folder(folder_id=folder_id).get()
except BoxAPIException as e:
if e.status == 404:
print(f"Folder {folder_id} not found\n")
return
print(f"Items in: {folder.name} {folder.id}")
print("-" * 80)
# grab the items in the folder
items = folder.get_items()
# filter out the files and get their details
files = [item.get() for item in items if item.type == "file"]
# sort the files by modified date
files.sort(key=lambda x: x.modified_at, reverse=True)
# print the files
for file in files:
# file = file.get()
print(f"{file.type} {file.modified_at} ({file.id}) {file.name} ")
# get the newest file
newest_file = files[0]
print(f"\nNewest file:{file.modified_at} {newest_file.name} {newest_file.id}")
Modifying the main method:
def main():
# service account
client = get_box_client(None)
# me = client.user().get()
# print(f"Service account: {me.name} {me.id}")
# folder_content(client)
# print(f"Service account: {me.name} {me.id}")
# folder_content(client, FOLDER_ID)
# as-user
user = client.user(USER_ID).get()
as_user_client = client.as_user(user)
me = as_user_client.user().get()
print(f"As-User account: {me.name} {me.id}")
files_in_folder(as_user_client, "165803865043")
Results in:
As-User account: Rui Barbosa 18622116055
Items in: Preview Samples 165803865043
--------------------------------------------------------------------------------
file 2023-05-17T06:50:27-07:00 (1216393081021) BoxAPISingDemoDoc (1) (2).pdf
file 2023-03-06T11:30:16-08:00 (974225001875) ZIP_renamed.zip
file 2023-03-06T11:23:12-08:00 (974207525964) Audio_renamed.mp3
file 2022-08-17T07:28:54-07:00 (997819641379) mov_bbb.mp4
file 2022-08-16T14:53:38-07:00 (997509657533) BoxAPISingDemoDoc (1) (1).pdf
file 2022-06-21T14:01:14-07:00 (974226696777) BoxAPISingDemoDoc (1).pdf
file 2022-06-21T13:55:01-07:00 (974229112148) Single Page.docx
file 2022-06-21T13:55:00-07:00 (974225083627) JSON.json
file 2022-06-21T13:55:00-07:00 (974225084827) Preview SDK Sample Excel.xlsx
file 2022-06-21T13:54:59-07:00 (974228631587) Document (Powerpoint).pptx
file 2022-06-21T13:54:59-07:00 (974209854641) HTML.html
file 2022-06-21T13:54:59-07:00 (974227441126) JS-Small.js
Newest file: BoxAPISingDemoDoc (1) (2).pdf 1216393081021
Not sure if time zones are important in this situation, but consider them.
Let us know if this works for you.
Cheers
@rbarbosa Thank you so much for your time!! It works.