Can't add an existing Media Item to a new Album via Google Photos API

61 views Asked by At

Goal

I am attempting to programmatically copy existing Media Items from one album to a newly created album.

For example, I have a photo with Media Item ID of p001 and it currently lives in an album that respectively has an ID of a001. I have programmatically created a new album of ID a002. I want to add photo p001 to album a002 programmatically.

Problem

The following error appears when making the API call to add the photo to the album:

"Request must contain a valid upload token."

There is a related issue of the inability to add media items to existing albums and my suspicion is that this is related, but not well documented (or maybe has poor discoverability).

Is this expected behavior?

Full Error Log

Error adding photo ID <REDACTED> to album ID <REDACTED> <HttpError 400 when requesting https://photoslibrary.googleapis.com/v1/mediaItems:batchCreate?alt=json returned "Request must contain a valid upload token.". Details: "Request must contain a valid upload token.">

My Implementation

I am attempting this via a Python 3.11 script as follows, where:

  • credentials.json contains the OAuth credentials to my API (I have verified this works, as I have successfully created an album programmatically).
  • photos.csv is a CSV file where the rows are defined as album_name,album_id,photo_name,photo_id, such as Album 1,a001,Photo 1,p001.
import csv
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build

# Path to your '.json' file for the new account
CREDENTIALS_FILE_PATH = './credentials.json'

SCOPES = ['https://www.googleapis.com/auth/photoslibrary']

def create_album(service, album_title):
    album_request_body = {
        'album': {'title': album_title}
    }
    created_album = service.albums().create(body=album_request_body).execute()
    return created_album['id']

def add_photo_to_album(service, photo_id, album_id):
    try:
        service.mediaItems().batchCreate(body={
            'newMediaItems': [{'simpleMediaItem': {'uploadToken': photo_id}}],
            'albumId': album_id
        }).execute()
    except Exception as e:
        print(f"Error adding photo ID {photo_id} to album ID {album_id}: {e}")

def main():
    # Authenticate with the new account
    flow = InstalledAppFlow.from_client_secrets_file(CREDENTIALS_FILE_PATH, SCOPES)
    creds = flow.run_local_server(port=0)
    service = build('photoslibrary', 'v1', credentials=creds, static_discovery=False)

    # Track the created albums to avoid duplicates
    created_albums = {}

    with open('photos.csv', 'r', newline='') as file:
        reader = csv.reader(file)
        next(reader)  # Skip header

        for album_name, _, photo_name, photo_id in reader:
            temp_album_name = f"{album_name}-TEMP"

            if temp_album_name not in created_albums:
                created_albums[temp_album_name] = create_album(service, temp_album_name)

            add_photo_to_album(service, photo_id, created_albums[temp_album_name])

if __name__ == '__main__':
    main()
0

There are 0 answers