Skip to content

Enhance usage API by exposing Analytics data#18

Draft
piyushryn wants to merge 2 commits into
mainfrom
IK-2639-Add-analytics-to-usage-api
Draft

Enhance usage API by exposing Analytics data#18
piyushryn wants to merge 2 commits into
mainfrom
IK-2639-Add-analytics-to-usage-api

Conversation

@piyushryn

Copy link
Copy Markdown
Contributor

Proposing these points

  • Clean uniform row shape (value, requests, bandwidthBytes) across every breakdown
    • value can be anything from url to countryName to error code
    • requests are the number of requests
    • bandwithBytes is the bandwidth in bytes
  • topBreakdownsByRequest and topBreakdownsByBandwidth as the two top-level sort buckets, visible duplication but a cleaner approach (we can also start accepting a sorting key to return bandwidth and requests separatly rather than a monolith response with both kinds of sorting )

Old response of the api

{
    "bandwidthBytes": 18273487,
    "mediaLibraryStorageBytes": 697650923,
    "videoProcessingUnitsCount": 232,
    "extensionUnitsCount": 0,
    "originalCacheStorageBytes": 0
}

Proposed new New Response Types

interface UsageReport {
  meta: UsageMeta;
  bandwidthBytes: Bytes;
  mediaLibraryStorageBytes: Bytes;
  videoProcessingUnitsCount: number;
  extensionUnitsCount: number;
  originalCacheStorageBytes: Bytes;
  requestCount: RequestCount;
  videoProcessingUnitsUsage: VideoProcessingUnitsUsage;
  extensionUnitsUsage: ExtensionUnitsUsage;
  topBreakdownsByRequest: TopBreakdowns;
  topBreakdownsByBandwidth: TopBreakdowns;
}

type DateString = string; // Example: "2026-06-01"
type Bytes = number;
type RequestCount = number;

interface UsageMeta {
  from: DateString;
  to: DateString;
}
interface VideoProcessingUnitsUsage {
  SD: number;
  HD: number;
  "4K": number;
  "8K": number;
  "16K": number;
}
interface ExtensionUnitsUsage {
  total: number;
  "aws-auto-tagging": number;
  "google-auto-tagging": number;
  "ai-auto-description": number;
  ikremovebg: number;
  "remove-bg": number;
  upscale: number;
  retouch: number;
  genvar: number;
  genfill: number;
  genimg: number;
  dropshadow: number;
  "change-bg": number;
  edit: number;
  "ai-tasks": number;
  "ai-video-transcription": number;
  "creative-banner": number;
}
interface BreakdownItem {
  value: string;
  requests: RequestCount;
  bandwidthBytes: Bytes;
}
interface GeographyBreakdownItem extends BreakdownItem {
  countryCode: string; // Example: "IN", "SG"
}

export interface TopBreakdowns {
  statusCodes: BreakdownItem[];
  formats: BreakdownItem[];
  cache: BreakdownItem[];
  geography: GeographyBreakdownItem[];
  devices: BreakdownItem[];
  transformations: BreakdownItem[];
  images: BreakdownItem[];
  videos: BreakdownItem[];
  others: BreakdownItem[];
  referral: BreakdownItem[];
  videoTransformations: BreakdownItem[];
  resultType: BreakdownItem[];
  userAgents: BreakdownItem[];
}

Proposed new New Response Example

{
  "meta": {
    "from": "2026-06-01",
    "to": "2026-06-26"
  },
  "bandwidthBytes": 18273487,
  "mediaLibraryStorageBytes": 697650923,
  "videoProcessingUnitsCount": 232,
  "extensionUnitsCount": 0,
  "originalCacheStorageBytes": 0,
  "requestCount": 160,
  "videoProcessingUnitsUsage": {
    "SD": 232,
    "HD": 0,
    "4K": 0,
    "8K": 0,
    "16K": 0
  },
  "extensionUnitsUsage": {
    "total": 0,
    "aws-auto-tagging": 0,
    "google-auto-tagging": 0,
    "ai-auto-description": 0,
    "ikremovebg": 0,
    "remove-bg": 0,
    "upscale": 0,
    "retouch": 0,
    "genvar": 0,
    "genfill": 0,
    "genimg": 0,
    "dropshadow": 0,
    "change-bg": 0,
    "edit": 0,
    "ai-tasks": 0,
    "ai-video-transcription": 0,
    "creative-banner": 0
  },
  "topBreakdownsByRequest": {
    "statusCodes": [
      {
        "value": "200",
        "requests": 148,
        "bandwidthBytes": 13924675
      },
      {
        "value": "404",
        "requests": 7,
        "bandwidthBytes": 4250
      },
      {
        "value": "206",
        "requests": 4,
        "bandwidthBytes": 4344030
      }
    ],
    "formats": [
      {
        "value": "image/webp",
        "requests": 119,
        "bandwidthBytes": 5261379
      },
      {
        "value": "image/jpeg",
        "requests": 20,
        "bandwidthBytes": 4570132
      },
      {
        "value": "video/webm",
        "requests": 8,
        "bandwidthBytes": 6727289
      }
    ],
    "cache": [
      {
        "value": "Miss",
        "requests": 96,
        "bandwidthBytes": 12276318
      },
      {
        "value": "Hit",
        "requests": 56,
        "bandwidthBytes": 5992387
      },
      {
        "value": "Error",
        "requests": 8,
        "bandwidthBytes": 4782
      }
    ],
    "geography": [
      {
        "value": "India",
        "countryCode": "IN",
        "requests": 136,
        "bandwidthBytes": 11218939
      },
      {
        "value": "Singapore",
        "countryCode": "SG",
        "requests": 22,
        "bandwidthBytes": 5669799
      }
    ],
    "devices": [
      {
        "value": "Desktop",
        "requests": 139,
        "bandwidthBytes": 16644941
      },
      {
        "value": "Smartphone",
        "requests": 17,
        "bandwidthBytes": 237432
      }
    ],
    "transformations": [
      {
        "value": "n-ik_ml_thumbnail",
        "requests": 80,
        "bandwidthBytes": 868433
      }
    ],
    "images": [
      {
        "value": "https://ik.imagekit.io/your_id/photo.jpeg",
        "requests": 80,
        "bandwidthBytes": 868433
      }
    ],
    "videos": [
      {
        "value": "https://ik.imagekit.io/your_id/clip.mp4",
        "requests": 8,
        "bandwidthBytes": 6727289
      }
    ],
    "others": [
      {
        "value": "https://ik.imagekit.io/your_id/design.psd",
        "requests": 2,
        "bandwidthBytes": 1389412
      }
    ],
    "referral": [],
    "videoTransformations": [],
    "resultType": [
      {
        "value": "Miss",
        "requests": 96,
        "bandwidthBytes": 12276318
      },
      {
        "value": "Hit",
        "requests": 56,
        "bandwidthBytes": 5992387
      },
      {
        "value": "Error",
        "requests": 8,
        "bandwidthBytes": 4782
      }
    ],
    "userAgents": [
      {
        "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36",
        "requests": 103,
        "bandwidthBytes": 10238534
      },
      {
        "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
        "requests": 22,
        "bandwidthBytes": 5669799
      }
    ]
  },
  "topBreakdownsByBandwidth": {
    "statusCodes": [
      {
        "value": "200",
        "requests": 148,
        "bandwidthBytes": 13924675
      },
      {
        "value": "206",
        "requests": 4,
        "bandwidthBytes": 4344030
      },
      {
        "value": "404",
        "requests": 7,
        "bandwidthBytes": 4250
      }
    ],
    "formats": [
      {
        "value": "video/webm",
        "requests": 8,
        "bandwidthBytes": 6727289
      },
      {
        "value": "image/webp",
        "requests": 119,
        "bandwidthBytes": 5261379
      },
      {
        "value": "image/jpeg",
        "requests": 20,
        "bandwidthBytes": 4570132
      }
    ],
    "cache": [
      {
        "value": "Miss",
        "requests": 96,
        "bandwidthBytes": 12276318
      },
      {
        "value": "Hit",
        "requests": 56,
        "bandwidthBytes": 5992387
      },
      {
        "value": "Error",
        "requests": 8,
        "bandwidthBytes": 4782
      }
    ],
    "geography": [
      {
        "value": "India",
        "countryCode": "IN",
        "requests": 136,
        "bandwidthBytes": 11218939
      },
      {
        "value": "Singapore",
        "countryCode": "SG",
        "requests": 22,
        "bandwidthBytes": 5669799
      }
    ],
    "devices": [
      {
        "value": "Desktop",
        "requests": 139,
        "bandwidthBytes": 16644941
      },
      {
        "value": "Smartphone",
        "requests": 17,
        "bandwidthBytes": 237432
      }
    ],
    "transformations": [
      {
        "value": "n-ik_ml_thumbnail",
        "requests": 80,
        "bandwidthBytes": 868433
      }
    ],
    "images": [
      {
        "value": "https://ik.imagekit.io/your_id/photo.jpeg",
        "requests": 80,
        "bandwidthBytes": 868433
      }
    ],
    "videos": [
      {
        "value": "https://ik.imagekit.io/your_id/clip.mp4",
        "requests": 8,
        "bandwidthBytes": 6727289
      }
    ],
    "others": [
      {
        "value": "https://ik.imagekit.io/your_id/design.psd",
        "requests": 2,
        "bandwidthBytes": 1389412
      }
    ],
    "referral": [],
    "videoTransformations": [],
    "resultType": [
      {
        "value": "Miss",
        "requests": 96,
        "bandwidthBytes": 12276318
      },
      {
        "value": "Hit",
        "requests": 56,
        "bandwidthBytes": 5992387
      },
      {
        "value": "Error",
        "requests": 8,
        "bandwidthBytes": 4782
      }
    ],
    "userAgents": [
      {
        "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36",
        "requests": 103,
        "bandwidthBytes": 10238534
      },
      {
        "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
        "requests": 22,
        "bandwidthBytes": 5669799
      }
    ]
  }
}

…eakdowns for analytics based on requests and bandwidth
@piyushryn piyushryn marked this pull request as draft June 26, 2026 12:35
@manu4543 manu4543 requested a review from Copilot June 30, 2026 05:06

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enhances the /v1/accounts/usage API schema by expanding the response to include analytics metadata and detailed breakdowns, enabling SDKs to expose richer usage/analytics data to clients.

Changes:

  • Adds meta date-range information and new aggregate counters (requestCount, detailed VPU/extension usage).
  • Introduces reusable component schemas for breakdown rows and breakdown collections (BreakdownItem, GeographyBreakdownItem, UsageBreakdowns, etc.).
  • Updates the endpoint example payload to reflect the richer analytics response, including top breakdowns sorted by requests and bandwidth.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread openapi/v1.0.0.yaml Outdated
topBreakdownsByBandwidth:
allOf:
- $ref: "#/components/schemas/UsageBreakdowns"
description: Top breakdowns ranked by bandwidth.
Comment thread openapi/v1.0.0.yaml
Comment thread openapi/v1.0.0.yaml Outdated

UsageMeta:
type: object
description: The date range the usage data covers.
Comment thread openapi/v1.0.0.yaml Outdated
requestCount:
type: integer
description: Number of requests made.
videoProcessingUnitsUsage:

@manu4543 manu4543 Jun 30, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

requestCount at the root is fine as it is an overall aggregation like bandwidthBytes, however everything else should be inside a new property named analytics.

So I suggest this shape, similar as yours with slight modifications.

Mainly mentioned integer in sdk as it would not be float, just verify we will be good as per response shape. If we sent double, sdk would break or cast incorrectly.

Then got rid of meta and GeographyBreakdownItem.

Consistently use requestCount instead of requests

Removing total from extensions breakdown, we have that at root already.

Removed cache as it was not clear to me what are we sending there. What is useful for user? Same for resultType.

We have to think about the case when we add new keys e.g. in extension breakdown. We cant send breaking change then. So either we start with generic object to being with or test it out in advance. Adding new keys in most sdk should not be breaking. Still better to include additionalProperty:true in oas in all nested objects? Other way is that we send it like array of {item:"name here e.g. 4K or extension name", value: integer}. This would cover both VPU and extension breakdown.

4K 8K 16K might not be good key names.

URL-endpoint wise data is missing but asked by customer. Mentioned in ticket

interface UsageReport {
  bandwidthBytes: integer;
  mediaLibraryStorageBytes: integer;
  videoProcessingUnitsCount: integer;
  extensionUnitsCount: integer;
  originalCacheStorageBytes: integer;
  requestCount: integer; // new property at root
  analytics: { // new property at root
    VPU: VPUBreakdown
    extensions: ExtensionBreakdown
    breakdowns: {
      byBandwidth: TopBreakdowns;
      byRequest: TopBreakdowns;
    }
  }
}

interface VPUBreakdown {
  SD: integer;
  HD: integer;
  "4K": integer;
  "8K": integer;
  "16K": integer;
}

interface ExtensionBreakdown {
  "aws-auto-tagging": integer;
  "google-auto-tagging": integer;
  "ai-auto-description": integer;
  ikremovebg: integer;
  "remove-bg": integer;
  upscale: integer;
  retouch: integer;
  genvar: integer;
  genfill: integer;
  genimg: integer;
  dropshadow: integer;
  "change-bg": integer;
  edit: integer;
  "ai-tasks": integer;
  "ai-video-transcription": integer;
  "creative-banner": integer;
}

interface BreakdownItem {
  value: string;
  requestCount: integer;
  bandwidthBytes: integer;
}

export interface TopBreakdowns {
  statusCodes: BreakdownItem[];
  formats: BreakdownItem[];
  geography: BreakdownItem[];
  devices: BreakdownItem[];
  imageTransformations: BreakdownItem[];
  videoTransformations: BreakdownItem[];
  image: BreakdownItem[];
  video: BreakdownItem[];
  others: BreakdownItem[];
  referral: BreakdownItem[];
  userAgents: BreakdownItem[];
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants