List Project Media
September 1, 2026
Table of contents
- What is listed
- Uploads vs generated media
- Request Headers
- Path Parameters
- Query Parameters
- Responses
- Model
- Examples
- Try It
List the media held in one project on a Google Flow account. Every entry comes back with a mediaGenerationId you can pass straight to DELETE /assets/email or GET /assets/mediaGenerationId.
This is the endpoint that shows you your uploads. Files you send with POST /assets stay on the Google account after the generation that used them is finished, and nothing removes them on its own — they simply accumulate. likelyUploads counts them, and likelyUpload marks each one.
Find a project id with GET /assets/projects/email, or omit projectId to read the project this account currently writes to.
What is listed
Two collections are merged into one media array: the project’s own timeline, and media attached to the project from elsewhere. The second is where uploads normally sit, and it is usually much the larger of the two — on a real account the project’s own timeline held 8 entries against 292 attached ones, every one of them an upload, some more than nine months old.
Both are listed together because both are stored on the account, both count toward it, and both can be deleted the same way.
Uploads vs generated media
likelyUpload reflects how Google itself recorded the media — as something you uploaded, or as something Flow generated. It is not inferred from the presence of a prompt or any other heuristic.
It is likelyUpload rather than isUpload for one reason: an entry Google records as neither stays false. Those show up as mediaType: "OTHER" and are left out of the likelyUploads count rather than being offered up for deletion on a guess.
https://api.useapi.net/v1/google-flow/assets/media/
Request Headers
Authorization: Bearer {API token}
API tokenis required, see Setup useapi.net for details.
Path Parameters
emailis required, URL-encoded. The Google Flow account holding the project.
Query Parameters
projectIdis optional. Defaults to the project this account currently writes to. Pass aprojectIdfrom GET /assets/projects/emailto read any other project on the account. It is required when the account has no project on file, in which case the call returns400without it.
There is no pagination — one call returns the whole project. A large project can return several hundred entries.
Responses
-
{ "email": "[email protected]", "projectId": "3a18acb1-2c6e-478b-bcec-2df19cb8edab", "count": 591, "likelyUploads": 388, "media": [ { "mediaGenerationId": "user:12345-email:6a6f...-image:0115f3c1-...redacted...", "mediaType": "IMAGE", "createTime": "2026-06-14T00:03:47.401463Z", "likelyUpload": true }, { "mediaGenerationId": "user:12345-email:6a6f...-video:a1d95d21-...redacted...", "mediaType": "VIDEO", "createTime": "2026-07-26T21:07:56.856451Z", "likelyUpload": false } ] }An empty project returns
200with an empty array, not404.{ "email": "[email protected]", "projectId": "3a18acb1-2c6e-478b-bcec-2df19cb8edab", "count": 0, "likelyUploads": 0, "media": [] } -
No
projectIdwas given and the account has no project on file. Pass one explicitly — GET /assets/projects/emaillists every project the account holds media in.{ "error": "Parameter projectId is required (this account has no project on file)" }The
projectIddoes not exist on this account, or is not a well-formed project id. Google’s own rejection is passed through unchanged, which is why this one does not read like the errors above. Both cases look identical, so check the value against GET /assets/projects/emailrather than trying to tell them apart from the response.{ "error": { "json": { "message": "Bad Request", "code": -32600, "data": { "code": "BAD_REQUEST", "httpStatus": 400, "path": "flow.projectInitialData", "zodError": null }, "status": 400 } } } -
Invalid API token.
{ "error": "Unauthorized" } -
The account named in the path is not configured for this token. List what is configured with GET /accounts.
{ "error": "Google Flow account [email protected] not found" } -
596 Session Error
Google session refresh failed. The account needs to be reconfigured. Delete the account using DELETE /accounts/
emailand add it again by strictly following the procedure in Setup Google Flow.{ "error": "Failed to refresh session: 500 Internal Server Error" }
Model
{
email: string // Echo of the path parameter
projectId: string // The project read, whether passed or defaulted
count: number // Length of media[]
likelyUploads: number // How many entries have likelyUpload: true
media: [{
mediaGenerationId: string // Send to DELETE /assets or GET /assets/{mediaGenerationId}
mediaType: 'IMAGE' | 'VIDEO' | 'OTHER'
createTime?: string // ISO 8601, absent on records Google returns without one
likelyUpload: boolean // True when Google recorded this as an upload
}]
error?: string // Present only on error responses
}
Examples
-
TOKEN='YOUR_API_TOKEN' EMAIL='[email protected]' ENCODED=$(printf %s "$EMAIL" | jq -sRr @uri) # The account's current project RESP=$(curl -s -H "Authorization: Bearer $TOKEN" \ "https://api.useapi.net/v1/google-flow/assets/media/$ENCODED") jq '{projectId, count, likelyUploads}' <<<"$RESP" # A specific project, listing the uploads oldest first PROJECT_ID='6db64a76-90a9-4ecd-99f0-cc524ec2b2af' curl -s -H "Authorization: Bearer $TOKEN" \ "https://api.useapi.net/v1/google-flow/assets/media/$ENCODED?projectId=$PROJECT_ID" \ | jq '[.media[] | select(.likelyUpload)] | sort_by(.createTime) | .[] | "\(.createTime) \(.mediaType) \(.mediaGenerationId)"' -r -
const token = 'YOUR_API_TOKEN'; const email = '[email protected]'; const params = new URLSearchParams(); // Omit projectId to read the account's current project // params.set('projectId', '6db64a76-90a9-4ecd-99f0-cc524ec2b2af'); const url = `https://api.useapi.net/v1/google-flow/assets/media/${encodeURIComponent(email)}` + (params.toString() ? `?${params}` : ''); const resp = await fetch(url, { headers: { 'Authorization': `Bearer ${token}` } }); if (!resp.ok) throw new Error(`${resp.status} ${await resp.text()}`); const { projectId, count, likelyUploads, media } = await resp.json(); console.log(`${projectId}: ${count} media, ${likelyUploads} uploads`); const uploads = media .filter(m => m.likelyUpload) .sort((a, b) => (a.createTime ?? '').localeCompare(b.createTime ?? '')); for (const m of uploads.slice(0, 10)) console.log(`${m.createTime} ${m.mediaType} ${m.mediaGenerationId}`); -
import requests from urllib.parse import quote token = 'YOUR_API_TOKEN' email = '[email protected]' url = f'https://api.useapi.net/v1/google-flow/assets/media/{quote(email, safe="")}' # Omit projectId to read the account's current project params = {} # params['projectId'] = '6db64a76-90a9-4ecd-99f0-cc524ec2b2af' resp = requests.get(url, headers={'Authorization': f'Bearer {token}'}, params=params) resp.raise_for_status() data = resp.json() print(f"{data['projectId']}: {data['count']} media, {data['likelyUploads']} uploads") uploads = sorted((m for m in data['media'] if m['likelyUpload']), key=lambda m: m.get('createTime') or '') for m in uploads[:10]: print(f"{m.get('createTime')} {m['mediaType']} {m['mediaGenerationId']}")