Required authentication scope
Uploading media items to a user’s library or album requires either the .appendonly
or the .photoslibrary
scope.
Media items can also be created using the .sharing
scope. To create items with the
.sharing
scope, you must first create an album and mark it as shared using
shareAlbum
. You can then create media items that are shared with the user in the album.
You can't create items directly in the user's library or in albums that your app hasn't shared.
When listing albums, the isWriteable
property indicates whether your application has
access to create media in a particular album.
The upload process
Uploading media items is a two-step process:
- Upload the raw bytes to a Google Server. This doesn't result in any media items being created in the user’s Google Photos account. Instead, it returns an upload token which identifies the uploaded bytes.
- Use the upload token to create the media item in the user’s Google Photos account. You can choose whether the media should be also added to a specific album. For more information, see Create albums.
Uploading bytes
Bytes are uploaded to Google using upload requests. If the upload request is successful, an
upload token which is in the form of a raw text string, is returned. To create media items, use
these tokens in the batchCreate
call.
REST
Include the following fields in the POST request header:
Header fields | |
---|---|
Content-type |
Set to application/octet-stream . |
X-Goog-Upload-File-Name |
Recommended. Set to the filename along with the file extension. Only the filename is shown to the user in Google Photos. |
X-Goog-Upload-Protocol |
Set to raw . |
Here is a POST request header:
POST https://photoslibrary.googleapis.com/v1/uploads Authorization: Bearer OAUTH2_TOKEN Content-type: application/octet-stream X-Goog-Upload-File-Name: FILENAME X-Goog-Upload-Protocol: raw
In the request body, include the binary of the file:
MEDIA_BINARY_DATA
If this POST request is successful, an upload token which is in the form of a raw text
string, is returned as the response body. To create media items, use these text strings in the
batchCreate
call.
UPLOAD_TOKEN
Java
try { // Create a new upload request // Specify the filename that will be shown to the user in Google Photos // and the path to the file that will be uploaded UploadMediaItemRequest uploadRequest = UploadMediaItemRequest.newBuilder() //filename of the media item along with the file extension .setFileName(mediaFileName) .setDataFile(new RandomAccessFile(pathToFile, "r")) .build(); // Upload and capture the response UploadMediaItemResponse uploadResponse = photosLibraryClient.uploadMediaItem(uploadRequest); if (uploadResponse.getError().isPresent()) { // If the upload results in an error, handle it Error error = uploadResponse.getError().get(); } else { // If the upload is successful, get the uploadToken String uploadToken = uploadResponse.getUploadToken().get(); // Use this upload token to create a media item } } catch (ApiException e) { // Handle error } catch (FileNotFoundException e) { // Local file could not be found for upload }
PHP
// Create a new upload request // Specify the filename that will be shown to the user in Google Photos // and the path to the file that will be uploaded // When specifying a filename, include the file extension try { $uploadToken = $photosLibraryClient->upload(file_get_contents($localFilePath), $filename); } catch (\GuzzleHttp\Exception\GuzzleException $e) { // Handle error }
The suggested file size for images is less than 50 MB. Files above 50 MB are prone to performance issues.
The Google Photos Library API supports resumable uploads. A resumable upload allows you to split a media file into multiple sections and upload one section at a time.
Creating a media item
After uploading media items to Google, you can create media items in Google Photos using upload tokens. An upload token is valid for one day after being created. A media item is always added to the user's library. Optionally, it can also be added to an album if your app has been granted permission.
Media items can be created only within the albums created by your app. For more information, see Authentication and authorization scopes.
To create new media items, call
mediaItems.batchCreate
by specifying a list of newMediaItems
. Each newMediaItem
contains an optional media description that is shown to the user. This description field is
restricted to 1000 characters. It also contains an upload token that's specified inside a
simpleMediaItem
.
For best performance, reduce the number of calls to mediaItems.batchCreate
you have
to make by including multiple media items in one call. Always wait until the previous request has
completed before making a subsequent call for the same user.
You can create a single media item or multiple media items in a user’s library by specifying the descriptions and corresponding upload tokens:
REST
Here is the POST request header:
POST https://photoslibrary.googleapis.com/v1/mediaItems:batchCreate Content-type: application/json Authorization: Bearer OAUTH2_TOKEN
The request body should specify a list of newMediaItems
.
{ "newMediaItems": [ { "description": "ITEM_DESCRIPTION", "simpleMediaItem": { "uploadToken": "UPLOAD_TOKEN" } } , ... ] }
Java
try { // Create a NewMediaItem with the uploadToken obtained from the previous upload request, and a description NewMediaItem newMediaItem = NewMediaItemFactory .createNewMediaItem(uploadToken, itemDescription); List<NewMediaItem> newItems = Arrays.asList(newMediaItem); BatchCreateMediaItemsResponse response = photosLibraryClient.batchCreateMediaItems(newItems); for (NewMediaItemResult itemsResponse : response.getNewMediaItemResultsList()) { Status status = itemsResponse.getStatus(); if (status.getCode() == Code.OK_VALUE) { // The item is successfully created in the user's library MediaItem createdItem = itemsResponse.getMediaItem(); } else { // The item could not be created. Check the status and try again } } } catch (ApiException e) { // Handle error }
PHP
try { $newMediaItems = []; $newMediaItems[0] = array( PhotosLibraryResourceFactory::newMediaItemWithDescription($uploadToken, $itemDescription)); $response = $photosLibraryClient->batchCreateMediaItems($newMediaItems); foreach ($response->getNewMediaItemResults() as $itemResult) { $status = $itemResult->getStatus(); if ($status->getCode() != Code::OK) { // Error when item is being created } } } catch (\Google\ApiCore\ApiException $e) { // Handle error }
You can add media items to the library and to an album by specifying the album id
.
For more information, see Create albums.
Each album can contain up to 20,000 media items. Requests to create media items in an album that would exceed this limit will fail.
REST
{ "albumId": "ALBUM_ID", "newMediaItems": [ { "description": "ITEM_DESCRIPTION", "simpleMediaItem": { "uploadToken": "UPLOAD_TOKEN" } } , ... ] }
Java
try { // Create new media items in a specific album BatchCreateMediaItemsResponse response = photosLibraryClient .batchCreateMediaItems(albumId, newItems); // Check the response } catch (ApiException e) { // Handle error }
PHP
try { $response = $photosLibraryClient->batchCreateMediaItems($newMediaItems, ['albumId' => $albumId]); } catch (\Google\ApiCore\ApiException $e) { // Handle error }
You can also specify albumId
and albumPosition
to insert media items
at a specific location in the album.
REST
{ "albumId": "ALBUM_ID", "newMediaItems": [ { "description": "ITEM_DESCRIPTION", "simpleMediaItem": { "uploadToken": "UPLOAD_TOKEN" } } , ... ], "albumPosition": { "position": "AFTER_MEDIA_ITEM", "relativeMediaItemId": "MEDIA_ITEM_ID" } }
Java
try { // Create new media items in a specific album, positioned after a media item AlbumPosition positionInAlbum = AlbumPositionFactory.createFirstInAlbum(); BatchCreateMediaItemsResponse response = photosLibraryClient .batchCreateMediaItems(albumId, newItems, positionInAlbum); // Check the response } catch (ApiException e) { // Handle error }
PHP
try { $albumPosition = PhotosLibraryResourceFactory::albumPositionAfterMediaItem($mediaItemId); $response = $photosLibraryClient->batchCreateMediaItems($newMediaItems, ['albumId' => $albumId, 'albumPosition' => $albumPosition]); } catch (\Google\ApiCore\ApiException $e) { // Handle error }
For more details regarding positioning in albums, see Add enrichments.
Item creation response
The mediaItems.batchCreate
call returns the result for each of the media items you
tried to create. The list of newMediaItemResults
indicates the status and includes
the uploadToken
for the request. A non-zero status code indicates an error.
REST
If all media items have been successfully created, the request returns HTTP status
200 OK
. If some some media items could not be created, the request returns HTTP
status 207 MULTI-STATUS
to indicate partial success.
{ "newMediaItemResults": [ { "uploadToken": "UPLOAD_TOKEN", "status": { "message": "OK" }, "mediaItem": { "id": "MEDIA_ITEM_ID", "productUrl": "https://photos.google.com/photo/PHOTO_PATH", "description": "ITEM_DESCRIPTION", "baseUrl": "BASE_URL-DO_NOT_USE_DIRECTLY", "mediaMetadata": { "width": "MEDIA_WIDTH_IN_PX", "height": "MEDIA_HEIGHT_IN_PX", "creationTime": "CREATION_TIME", "photo": {} }, } }, { "uploadToken": "UPLOAD_TOKEN", "status": { "code": 13, "message": "Internal error" } } ] }
Java
BatchCreateMediaItemsResponse response = photosLibraryClient.batchCreateMediaItems(newItems); // The response contains a list of NewMediaItemResults for (NewMediaItemResult result : response.getNewMediaItemResultsList()) { // Each result item is identified by its uploadToken String uploadToken = result.getUploadToken(); Status status = result.getStatus(); if (status.getCode() == Code.OK_VALUE) { // If the request is successful, a MediaItem is returned MediaItem mediaItem = result.getMediaItem(); String id = mediaItem.getId(); String productUrl = mediaItem.getProductUrl(); // ... } }
PHP
// The response from a call to batchCreateMediaItems returns a list of NewMediaItemResults foreach ($response->getNewMediaItemResults() as $itemResult) { // Each result item is identified by its uploadToken $itemUploadToken = $itemResult->getUploadToken(); // Verify the status of each entry to ensure that the item has been uploaded correctly $itemStatus = $itemResult->getStatus(); if ($itemStatus->getCode() != Code::OK) { // Error when item is being created } else { // Media item is successfully created // Get the MediaItem object from the response $mediaItem = $itemResult->getMediaItem(); // It contains details such as the Id of the item, productUrl $id = $mediaItem->getId(); $productUrl = $mediaItem->getProductUrl(); // ... } }
If an item is successfully added, a mediaItem
is returned that contains its
mediaItemId
, productUrl
and mediaMetadata
. For more
information, see Access media items.
If the media item is a video, it must be processed first. The mediaItem
contains a
status
inside its mediaMetadata
that describes the processing state of the
video file. A newly uploaded file returns the PROCESSING
status first, before it is
READY
for use. For details, see Access media items.
If you encounter an error during this call, follow the Best practices
and retry your request with the uploadToken
. You may want to keep track of successful
additions, so the image can be inserted into the album at the correct position during the next
request. For more information, see Create albums.
Results are always returned in the same order in which upload tokens were submitted.