Delete Account Media

September 1, 2026

Table of contents

  1. Explicit ids only
  2. Ids are validated before anything is deleted
  3. Request Headers
  4. Path Parameters
  5. Request Body
  6. Responses
  7. Model
  8. Examples
  9. Try It

Permanently delete media from a Google Flow account, addressed by mediaGenerationId, up to 100 per call.

Warning: this cannot be undone. The media is removed from the Google account itself, not from a useapi.net cache — there is no restore, and useapi.net keeps no copy to fall back on. Download anything you want to keep with GET /assets/mediaGenerationId before deleting it.

The usual reason to reach for this is accumulated uploads. Images and videos you send with POST /assets stay on the account indefinitely, and nothing else removes them. List them with GET /assets/media/email, which marks each entry with likelyUpload.

Explicit ids only

There is no wildcard, no “delete everything older than”, and no project-wide purge. Every id you send has to have come from a listing you already read.

This is deliberate. The action is irreversible on somebody’s real Google account, and the blast radius of a filter that matches more than you meant is the whole account.

Ids are validated before anything is deleted

The whole batch is checked first — format, ownership, account and type — and a single bad id fails the entire call with nothing deleted. You never end up guessing which half of a batch went through.

Ownership is enforced from the id itself: a mediaGenerationId encodes the useapi.net user it belongs to, so an id from another user is rejected with 403 before Google is contacted at all.

https://api.useapi.net/v1/google-flow/assets/email

Request Headers

Authorization: Bearer {API token}
Content-Type: application/json

Path Parameters

  • email is required, URL-encoded. The Google Flow account to delete from. Every id in the body must belong to this account — a mismatch is rejected with 400 rather than silently deleting from somewhere else.

Request Body

{
  "mediaGenerationIds": [
    "user:12345-email:6a6f...-image:0115f3c1-...",
    "user:12345-email:6a6f...-video:a1d95d21-..."
  ],
  "projectId": "3a18acb1-2c6e-478b-bcec-2df19cb8edab"
}
  • mediaGenerationIds is required. A non-empty array of 1 to 100 ids, each of type image or video. Take them from GET /assets/media/email, or from the media[] of any generation response.
  • projectId is optional and defaults to the project this account currently writes to. You rarely need it: media is resolved by its own id, so an asset listed under one project is deleted correctly whichever project you name. Set it only when the account has no project on file, where omitting it returns 400.

Responses

  • 200 OK

    Google accepted the batch.

    {
      "deleted": 2,
      "projectId": "3a18acb1-2c6e-478b-bcec-2df19cb8edab",
      "email": "[email protected]"
    }
    

    deleted is how many ids the accepted batch carried, which is always the number you sent. It is not a count of records that turned out to exist — deleting an id that is already gone succeeds rather than failing. To confirm what an account now holds, re-read GET /assets/media/email.

  • 400 Bad Request

    Nothing is deleted for any of these. Fix the request and send it again.

    The body was missing or not valid JSON.

    {
      "error": "Body must be JSON"
    }
    

    mediaGenerationIds was absent, empty, or not an array.

    {
      "error": "Body field mediaGenerationIds must be a non-empty array"
    }
    

    An entry is not a string, or is an empty one.

    {
      "error": "Body field mediaGenerationIds must contain non-empty strings"
    }
    

    More than 100 ids in one call. Split the work into batches.

    {
      "error": "Body field mediaGenerationIds accepts at most 100 ids, got 137"
    }
    

    An entry could not be parsed as a mediaGenerationId.

    {
      "error": "Invalid mediaGenerationId format: not-a-valid-ref-id"
    }
    

    An id belongs to a different Google Flow account than the one in the path. Send it in a separate call naming that account.

    {
      "error": "mediaGenerationId belongs to [email protected], not [email protected]"
    }
    

    An id is a character or voice reference. Those have their own endpoints — DELETE /characters/ref and DELETE /voices/ref.

    {
      "error": "mediaGenerationId type must be 'image' or 'video', got 'character'"
    }
    

    No projectId was given and the account has no project on file.

    {
      "error": "Body field projectId is required (this account has no project on file)"
    }
    
  • 401 Unauthorized

    Invalid API token.

    {
      "error": "Unauthorized"
    }
    
  • 403 Forbidden

    One of the ids belongs to a different useapi.net user than the one identified by the Authorization token. Nothing is deleted, and Google is never contacted.

    {
      "error": "Unauthorized access to user:99999 detected in mediaGenerationId"
    }
    
  • 404 Not Found

    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/email and add it again by strictly following the procedure in Setup Google Flow.

    {
      "error": "Failed to refresh session: 500 Internal Server Error"
    }
    

Model

{
  deleted: number      // How many ids the accepted batch carried
  projectId: string    // The project named in the request, or the account's current one
  email: string        // Echo of the path parameter
  error?: string       // Present only on error responses
}

Examples

  • TOKEN='YOUR_API_TOKEN'
    EMAIL='[email protected]'
    ENCODED=$(printf %s "$EMAIL" | jq -sRr @uri)
    
    # Delete two specific assets
    curl --location --request DELETE \
      "https://api.useapi.net/v1/google-flow/assets/$ENCODED" \
      --header "Authorization: Bearer $TOKEN" \
      --header 'Content-Type: application/json' \
      --data '{
        "mediaGenerationIds": [
          "user:12345-email:6a6f...-image:0115f3c1-...",
          "user:12345-email:6a6f...-video:a1d95d21-..."
        ]
      }'
    
    # Or clear out uploads older than a cut-off, 100 at a time.
    # Read the listing first, eyeball it, and only then delete.
    CUTOFF='2026-01-01'
    
    curl -s -H "Authorization: Bearer $TOKEN" \
      "https://api.useapi.net/v1/google-flow/assets/media/$ENCODED" \
    | jq --arg cutoff "$CUTOFF" '[.media[]
        | select(.likelyUpload and .createTime != null and .createTime < $cutoff)
        | .mediaGenerationId]' > /tmp/stale.json
    
    echo "$(jq length /tmp/stale.json) uploads older than $CUTOFF"
    
    jq -c 'range(0; length; 100) as $i | .[$i:$i+100]' /tmp/stale.json | while read -r BATCH; do
      jq -n --argjson ids "$BATCH" '{mediaGenerationIds: $ids}' \
      | curl -s --location --request DELETE \
          "https://api.useapi.net/v1/google-flow/assets/$ENCODED" \
          --header "Authorization: Bearer $TOKEN" \
          --header 'Content-Type: application/json' \
          --data @-
      echo
    done
    
  • const token = 'YOUR_API_TOKEN';
    const email = '[email protected]';
    const encoded = encodeURIComponent(email);
    const headers = {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    };
    
    const listResp = await fetch(
      `https://api.useapi.net/v1/google-flow/assets/media/${encoded}`,
      { headers: { 'Authorization': `Bearer ${token}` } });
    const { media } = await listResp.json();
    
    const cutoff = '2026-01-01';
    const stale = media
      .filter(m => m.likelyUpload && m.createTime && m.createTime < cutoff)
      .map(m => m.mediaGenerationId);
    
    console.log(`${stale.length} uploads older than ${cutoff}`);
    
    let removed = 0;
    for (let i = 0; i < stale.length; i += 100) {
      const batch = stale.slice(i, i + 100);
      const resp = await fetch(
        `https://api.useapi.net/v1/google-flow/assets/${encoded}`,
        { method: 'DELETE', headers, body: JSON.stringify({ mediaGenerationIds: batch }) });
    
      if (!resp.ok) throw new Error(`${resp.status} ${await resp.text()}`);
      removed += (await resp.json()).deleted;
    }
    console.log(`Deleted ${removed}`);
    
  • import requests
    from urllib.parse import quote
    
    token = 'YOUR_API_TOKEN'
    email = '[email protected]'
    encoded = quote(email, safe='')
    base = 'https://api.useapi.net/v1/google-flow'
    headers = {'Authorization': f'Bearer {token}'}
    
    listing = requests.get(f'{base}/assets/media/{encoded}', headers=headers)
    listing.raise_for_status()
    
    cutoff = '2026-01-01'
    stale = [m['mediaGenerationId'] for m in listing.json()['media']
             if m['likelyUpload'] and m.get('createTime') and m['createTime'] < cutoff]
    
    print(f'{len(stale)} uploads older than {cutoff}')
    
    removed = 0
    for i in range(0, len(stale), 100):
        resp = requests.delete(f'{base}/assets/{encoded}', headers=headers,
                               json={'mediaGenerationIds': stale[i:i + 100]})
        resp.raise_for_status()
        removed += resp.json()['deleted']
    
    print(f'Deleted {removed}')
    

Try It