April 28, 2026

API Key Client Grouping for Resellers and Multi-Tenant SaaS

api-key-managementresellermulti-tenantbillingbest-practices

If you're an agency, contracting firm, or SaaS operator embedding a PDF generation API into a service used by multiple clients, the most painful monthly task is usually the same: figuring out which key belongs to which client, and how much each client used.

FUNBREW PDF solves this with client labels and tags on every API key. Generated PDFs, API logs, and usage data can all be filtered and aggregated per client, with CSV exports that include the client label so you can produce billing-allocation evidence in one click. See the full reseller patterns on the use cases page.

This guide walks through the operational pattern and best practices for reseller scenarios.

Why API key grouping matters

Common operational pain points

  • Manual invoice allocation: spending the last day of every month aggregating "Acme used 10,000, Beta used 3,000" by hand
  • Logs that can't be sliced: when something breaks for one client, you have to search the entire log stream
  • Tribal knowledge: "wait, whose key is sk-xxxxx again?" — newcomers can't tell

What grouping fixes

Pain point After grouping
Manual invoice allocation Just look at the client_label column in the CSV
Filtering logs One click per client
Tribal knowledge Visible at a glance in the dashboard

When to use client_label vs tags

When in doubt, use the table below. The rule of thumb: the unit you want to split invoices by goes in client_label; everything else is a tag.

client_label tags
Count Exactly one Multiple allowed
Role Primary axis for billing and aggregation Sub-classification (environment, use case, etc.)
Example Acme Inc production, invoice-pdf
CSV export Included as the client_label column (invoice evidence) Not exported today — dashboard-only
Naming drift Breaks filtering — use a strict convention More forgiving

How to use it

Step 1: Tag each API key with client information

Dashboard → API Keys → "New key" or "Edit" on an existing key.

  • Key name: an internal label (e.g. Acme Production)
  • Client / Project: the client company or project name (e.g. Acme Inc)
  • Tags: environment or purpose (e.g. production, invoice-pdf)

Tip: When you issue several keys for the same client (per environment, per use case), set the same client_label on all of them. The dashboard will then aggregate them into a single client view.

Step 2: Filter PDFs and logs by client

The PDF list and API log pages now have a "Client" filter.

If multiple keys share the same client_label (e.g. Acme's production key and staging key), the filter shows PDFs from both keys combined. The aggregation happens at the client level, not the key level.

Step 3: Export CSV for billing allocation

Running CSV export from the PDF list produces:

filename,original_name,source_type,file_size,download_count,...,api_key,client_label
abc123.pdf,"acme-invoice-2026-04.pdf",html,254078,1,...,Acme Production,Acme Inc
def456.pdf,"beta-contract.pdf",html,128400,2,...,Beta Production,Beta Corp

Pivot on client_label and you instantly have per-client generation counts, file sizes, and download counts. Monthly billing becomes nearly self-serve.

Best practices by reseller scenario

Scenario 1: Agency model (separate billing per client)

client_label: "Acme Inc"       tags: ["production"]
client_label: "Acme Inc"       tags: ["staging"]
client_label: "Beta Corp"      tags: ["production"]
client_label: "Gamma Studio"   tags: ["production", "trial"]
  • Group monthly CSV by client_label → use as the basis for each client's invoice
  • Mark trials with a trial tag and update to production on conversion

Scenario 2: Multi-tenant SaaS

client_label: "tenant_001"  tags: ["plan:pro", "production"]
client_label: "tenant_002"  tags: ["plan:enterprise", "production"]
  • Use the tenant ID as client_label so it joins cleanly against your own DB
  • Keep plan info in tags to detect overage candidates

Scenario 3: Project-based contracting

client_label: "Project Alpha"  tags: ["delivered", "support-2026"]
client_label: "Project Beta"   tags: ["development"]
  • Tag delivered projects with delivered, and use support-yyyy for active warranty windows
  • Pull only the relevant logs when a support ticket lands

Design considerations

Grouping is a management label

client_label and tags are metadata for filtering and aggregation in the dashboard. They do not change API behavior (rate limiting, billing, scopes). To enforce per-client rate limits, keep using separate keys; grouping just makes them easier to manage.

Keep keys safe

Rather than handing API keys directly to clients, the recommended reseller pattern is to proxy client requests through your own backend, which holds the FUNBREW PDF key. Issue separate keys per client, label them, and a leak only impacts one client — rotation stays surgical.

Decide on a naming convention up front

When several people manage keys, label drift (Acme Inc / acme inc / Acme Inc.) breaks filtering. Agree on a convention (e.g. legal name, single space, no honorifics) before you start tagging.

Summary

For anyone reselling a PDF generation API, key grouping makes three things dramatically easier: invoice allocation, support response, and operational handoffs.

  • client_label aggregates per client
  • tags slice further by environment or purpose
  • CSV exports automate billing allocation

Already issued keys? Just edit them in the dashboard to add client_label and tags — past PDFs and logs are filterable retroactively.

Read the full documentation or head to the API keys dashboard to start grouping. To experiment with the API itself first, try the playground. For a broader take on invoice automation, see the invoice API guide.

Cost allocation patterns

Beyond simple per-client grouping, many resellers need to track costs at a finer granularity — by cost center, billing period, or service tier. The patterns below combine client_label with tags to build a lightweight cost allocation system without external tooling.

Pattern: per-department cost centers

When a single enterprise client has multiple internal departments, issue one key per department and set the department name as a tag. Keep the client_label consistent across all departmental keys so the CSV rolls up cleanly at the account level.

client_label: "Acme Corp"   tags: ["dept:finance",    "production"]
client_label: "Acme Corp"   tags: ["dept:legal",      "production"]
client_label: "Acme Corp"   tags: ["dept:marketing",  "production"]

At month end, export the CSV and pivot first by client_label (for the invoice to Acme Corp) and then filter by the dept:* tags to produce per-department breakdowns for their internal showback reports. No extra infrastructure needed.

Pattern: tiered pricing with usage caps

SaaS operators who resell PDF generation at different plan tiers can encode the tier in a tag and enforce limits programmatically.

client_label: "tenant_A"   tags: ["plan:starter",    "production"]   # cap: 500 PDFs/mo
client_label: "tenant_B"   tags: ["plan:growth",     "production"]   # cap: 5 000 PDFs/mo
client_label: "tenant_C"   tags: ["plan:enterprise", "production"]   # cap: unlimited

Your billing service queries the FUNBREW PDF API for monthly usage per key, compares it against the cap for each plan, and either blocks generation or triggers an upsell flow. Because the plan is in the tag, plan changes only require updating one field — no structural changes to your key topology.

Pattern: project-lifecycle cost tracking

For agencies billing project-by-project, you often need to distinguish pre-production spend (scoping, prototyping) from production spend billed to the client.

client_label: "Project Omega"   tags: ["phase:prototype", "internal"]
client_label: "Project Omega"   tags: ["phase:production", "billable"]

Filter the CSV for billable to produce the client-facing invoice. Keep the internal rows for your own P&L tracking. When the project closes, add a delivered tag and stop rotating the keys — the label history stays in the CSV archive.

Usage alert patterns

Proactive usage monitoring prevents bill shock and helps you enforce plan limits before they become support incidents. Because FUNBREW PDF exposes usage data through its API, you can build lightweight alerting with standard tooling.

Alerting with a cron script

// scripts/usage-alert.js
// Run daily via cron or a scheduled Lambda to warn before clients hit their caps

import axios from 'axios';

const API_KEY  = process.env.FUNBREW_API_KEY;
const API_URL  = process.env.FUNBREW_API_URL || 'https://api.pdf.funbrew.cloud/v1';
const SLACK_WEBHOOK = process.env.SLACK_WEBHOOK_URL;

// Map client labels to their monthly PDF caps
const LIMITS = {
  'Acme Inc':   5000,
  'Beta Corp':  1000,
  'Gamma LLC':  2500,
};

async function checkUsage() {
  const { data } = await axios.get(`${API_URL}/usage/monthly`, {
    headers: { Authorization: `Bearer ${API_KEY}` },
  });

  for (const [client, usage] of Object.entries(data.byClient)) {
    const cap = LIMITS[client];
    if (!cap) continue;

    const pct = (usage.count / cap) * 100;

    if (pct >= 90) {
      await sendSlackAlert(client, usage.count, cap, pct);
    }
  }
}

async function sendSlackAlert(client, used, cap, pct) {
  const msg = `*PDF usage alert* — ${client}: ${used.toLocaleString()} / ${cap.toLocaleString()} PDFs (${pct.toFixed(0)}%)`;
  await axios.post(SLACK_WEBHOOK, { text: msg });
}

checkUsage().catch(console.error);

Wire this to a cron job or an AWS EventBridge rule and you get a Slack ping when any client exceeds 90% of their cap — before they hit the wall.

Using webhook events for real-time tracking

If you prefer event-driven monitoring, the FUNBREW PDF webhook integration fires on every successful PDF generation. Subscribe to the pdf.created event and pipe it to your counting logic:

// Pseudocode: increment a Redis counter per client on every pdf.created event
app.post('/webhooks/pdf', async (req, res) => {
  const { event, payload } = req.body;
  if (event !== 'pdf.created') return res.sendStatus(204);

  const client = payload.client_label;
  const key    = `usage:${client}:${currentMonth()}`;

  await redis.incr(key);
  await redis.expire(key, 60 * 60 * 24 * 35); // keep for ~35 days

  // Check against cap
  const count = await redis.get(key);
  const cap = LIMITS[client];
  if (cap && count >= cap * 0.9) {
    await triggerAlert(client, count, cap);
  }

  res.sendStatus(204);
});

This gives you sub-second usage counters per client without polling the API. See the webhook payload guide for the full event schema.

Client onboarding flow

Bringing a new client online consistently is harder than it sounds when you have a dozen keys in flight. The following checklist and code snippet standardize onboarding to three minutes or less.

Onboarding checklist

  1. Create API key(s) — one per environment (production + staging minimum)
  2. Set client_label — use the client's legal entity name or tenant ID (decide convention first)
  3. Set tags — environment (production, staging), plan tier (plan:growth), and any other axes you filter on
  4. Add to LIMITS map — update your usage-alert script with the client's cap
  5. Share credentials securely — do not email raw keys; use a secrets manager or a one-time-link tool
  6. Smoke-test — generate one PDF via the playground with the new key to confirm it works
  7. Document — add the client to your internal key registry (even a spreadsheet works if the naming is consistent)

Automating key creation

For high-volume onboarding, create keys via the FUNBREW PDF REST API rather than the dashboard:

# Create a production key for a new client
curl -X POST https://api.pdf.funbrew.cloud/v1/api-keys \
  -H "Authorization: Bearer $FUNBREW_MASTER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name":         "Acme Inc — Production",
    "client_label": "Acme Inc",
    "tags":         ["production", "plan:growth"]
  }'

Store the returned key value in your secrets manager immediately — it is shown only once. Then update your LIMITS map and alert subscriptions before the client sends their first request.

Offboarding a client

When a client relationship ends, rotate or revoke the key(s) from the dashboard. The historical CSV data remains queryable by client_label even after the key is revoked, so you can still produce a final usage report for the closing invoice.

# Revoke a key (replace KEY_ID with the actual key ID)
curl -X DELETE https://api.pdf.funbrew.cloud/v1/api-keys/KEY_ID \
  -H "Authorization: Bearer $FUNBREW_MASTER_KEY"

After revocation, export a final CSV filtered to that client_label and archive it alongside the project files. Any future support queries can be answered from the archive without needing live API access.

Putting it all together

The three capabilities above — grouping, cost allocation, and alerting — compose naturally into a lightweight client management layer on top of the FUNBREW PDF API.

Capability Mechanism Maintenance effort
Per-client visibility client_label on every key Once at onboarding
Invoice evidence CSV export, pivot by client_label Monthly, ~5 minutes
Sub-client chargebacks tags like dept:finance Once per cost center
Plan enforcement Usage API + cron script One-time setup
Real-time tracking Webhook → Redis counter One-time setup
New client onboarding Dashboard or REST API Per client, ~3 minutes

For teams generating high PDF volumes, also review the batch processing guide and the rate limiting guide — both become relevant once a single client starts pushing thousands of PDFs per hour.

For security considerations around key storage and rotation across multiple clients, the API security guide covers secret management, proxy patterns, and audit logging in detail.

Powered by FUNBREW PDF