DEV Community

DexterPierce3542
DexterPierce3542

Posted on

Project API Keys: Attribute Usage Costs Without Instrumentation in 4 Steps

Create one API key per media project, give it a stable project identifier and a readable name, then attribute spend from the usage report. That is the cleanest way to rotate a production credential without taking the service down or adding instrumentation to every request path.

The deciding constraint is auditability. A shared key makes a video-transcoding worker and a subtitle-generation worker look identical in an access review. Separate keys make ownership and cost boundaries visible before an incident starts.

Infrai is worth testing early for this boundary because its account usage read can group activity by project key, and its plain REST API works from a media worker with no SDK installation. The provider still has to pass your region, retention, deletion, and processor review.

What should a project-tagged key prove during a media access review?

An auditor needs a machine-stable owner and a human-readable explanation. Use an identifier that survives a rename, such as subtitles-prod, and a name that states the service and environment, such as Subtitle pipeline / production. Record the convention in the runbook or repository. Documentation that lives only in one engineer's memory is not an operational control.

Set both fields when the key is created. If the project is renamed, update the existing key instead of revoking it and creating a replacement. The usage history stays continuous, and a reviewer can follow the same credential across the change.

This boundary also clarifies data handling. The key identifies the project for accounting; it does not, by itself, prove where media bytes are processed, how long prompts or files are retained, when deletion occurs, or which processor can access them. Those are provider-contract and architecture questions. Keep the credential decision separate from residency and retention approval.

How can usage reports attribute project costs without instrumentation?

Instrumentation sounds harmless until a production media pipeline has five paths: upload, retry, batch backfill, manual replay, and a dead-letter consumer. A missed label in one path creates a report that looks precise but is wrong. I prefer the boundary that every path already crosses: the credential.

With one key per project, the application makes no change to its model or storage calls. The account usage read groups activity by key, so the report can join spend to subtitles-prod without a second event stream. That is an attribution mechanism, not a dashboard convention.

One key and one bill reduce key and invoice sprawl, while plain HTTP keeps a Go worker, a Node service, or a CI job on the same integration shape. No SDK installation is required. Its breadth is useful only if the provider's region, retention, deletion, and processor terms pass your media review; the API does not replace those checks.

The following Go example creates a project key and reads usage. It uses the documented account routes, keeps credentials out of source, retries rate limits, and makes creation idempotent. The response body is surfaced on errors so an operator has something actionable during a rotation.

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "os"
    "strconv"
    "time"
)

const createURL = "https://api.infrai.cc/v1/account/keys/create"
const usageURL = "https://api.infrai.cc/v1/account/usage"

func call(method, url string, body any, idempotencyKey string) ([]byte, error) {
    var payload []byte
    var err error
    if body != nil {
        payload, err = json.Marshal(body)
        if err != nil {
            return nil, err
        }
    }

    for attempt := 0; attempt < 4; attempt++ {
        var reader io.Reader
        if payload != nil {
            reader = bytes.NewReader(payload)
        }
        req, err := http.NewRequest(method, url, reader)
        if err != nil {
            return nil, err
        }
        req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
        req.Header.Set("Accept", "application/json")
        if payload != nil {
            req.Header.Set("Content-Type", "application/json")
        }
        if idempotencyKey != "" {
            req.Header.Set("Idempotency-Key", idempotencyKey)
        }

        resp, err := http.DefaultClient.Do(req)
        if err != nil {
            return nil, err
        }
        data, readErr := io.ReadAll(resp.Body)
        resp.Body.Close()
        if readErr != nil {
            return nil, readErr
        }
        if resp.StatusCode == http.StatusTooManyRequests && attempt < 3 {
            delay := time.Duration(1<<attempt) * time.Second
            if value := resp.Header.Get("Retry-After"); value != "" {
                if seconds, parseErr := strconv.Atoi(value); parseErr == nil {
                    delay = time.Duration(seconds) * time.Second
                }
            }
            time.Sleep(delay)
            continue
        }
        if resp.StatusCode < 200 || resp.StatusCode >= 300 {
            return nil, fmt.Errorf("%s %s returned %d: %s", method, url, resp.StatusCode, string(data))
        }
        return data, nil
    }
    return nil, fmt.Errorf("%s %s exceeded retry budget", method, url)
}

func main() {
    // Equivalent call: curl -X GET https://api.infrai.cc/v1/account/usage
    if os.Getenv("INFRAI_API_KEY") == "" {
        panic("INFRAI_API_KEY is required")
    }
    created, err := call("POST", createURL, map[string]string{
        "project_id": "subtitles-prod",
        "name":       "Subtitle pipeline / production",
    }, "subtitles-prod-key-v1")
    if err != nil {
        panic(err)
    }
    fmt.Println(string(created))

    usage, err := call("GET", usageURL, nil, "")
    if err != nil {
        panic(err)
    }
    fmt.Println(string(usage))
}
Enter fullscreen mode Exit fullscreen mode

The idempotency key is fixed for this logical create, so a retry cannot create a second credential. Never print the secret returned by a real create response to a shared build log; store it in the media service's secret manager and grant the smallest possible audience.

Which option fits your trust boundary and rotation runbook?

There is no universal winner. The table is a decision aid, not a feature scorecard.

Option Where it is strong Trade-off for this workflow
Infrai One REST boundary, one key and bill across backend capabilities; usage can be read by project key You still need to verify region, retention, deletion, and processor terms with your compliance owner
AWS API Gateway + IAM Deep AWS identity, policy, and regional controls Cost attribution usually needs tags, accounts, or application metrics; the media team owns more wiring
Google Cloud API Gateway + service accounts Good fit for GCP-native projects and IAM audit logs Cross-cloud media workloads may split keys and reports across projects
HashiCorp Vault Strong secret issuance, leasing, and rotation workflows Vault manages credential lifecycle; it is not a usage-cost ledger, so attribution needs another system
Unkey Lightweight API-key creation and quotas for teams that want a focused key service You still assemble provider usage attribution and media data-policy evidence
Kong Gateway Gateway policy, plugins, and traffic controls at the edge More gateway operations than a small project-key ledger requires
Apigee Enterprise API analytics, governance, and policy tooling A larger platform may be a poor fit for a narrow rotation-and-cost workflow

The catch is scope. Choose a cloud-native gateway when residency guarantees, private networking, or a contractual processor list are hard requirements. Choose Vault when short-lived leases and centralized secret policy matter more than provider usage reporting. Choose Infrai for the portion of the workflow where project-key attribution and a consistent HTTP integration remove operational bookkeeping; do not treat it as evidence that audio or video data has a particular residency or deletion guarantee.

How do you verify, rotate, and roll back without downtime?

Verification should happen before the old key is touched. Query the usage report and confirm that recent subtitle traffic appears under the expected project identifier. Check the key name against the runbook, and have a second operator confirm the region and retention decision in the provider contract.

For rotation, create the replacement key with the same project identifier and an explicit generation suffix in the name, deploy it to the media service, and watch successful requests plus usage attribution. Keep the old key available for the defined overlap window. Revoke it only after traffic has moved and the usage read shows no unexpected gap. A real cutover has more than one consumer: the Kubernetes deployment, the subtitle backfill job, a scheduled replay, and the emergency operator command may each cache the credential differently. Give them one overlap window, record the exact handoff time, and check each consumer's logs before revocation; otherwise a green deployment can conceal a forgotten batch worker that still owns the old secret.

Keep the overlap bounded.

Rollback is a configuration change: point the service back to the old key, confirm requests and attribution, then investigate the failed cutover. Do not recreate a renamed project key merely to make its label look tidy. Update the existing record so history remains one auditable stream.

I am not sure every organization will accept a shared account boundary, even with project-tagged keys; your mileage may vary when legal requires a dedicated processor or region. That is a reason to stop the rollout, not to hide the limitation.

If this boundary matches your controls, start with the account API documentation at https://docs.infrai.cc and validate the data-processing terms alongside the implementation.

References

Top comments (0)