Build Self-Serve API Key Management in Your Product
If you want your users to create, view, rotate, and delete API keys from within your own application rather than the Zuplo Developer Portal, you can build that experience using the Zuplo Developer API. This guide walks through the architecture, the API operations you need, and the security considerations for a production integration.
Architecture
A self-serve integration has three parts:
- Your frontend — the settings page or dashboard where users manage their keys.
- Your backend — a server-side proxy that authenticates the user with your own auth system, then calls the Zuplo Developer API on their behalf.
- Zuplo Developer API — the management API at
https://dev.zuplo.comthat handles consumer and key CRUD operations.
Code
The frontend calls API routes on your backend (for example, /api/keys), which
authenticate the user and proxy the request to Zuplo. The frontend never
communicates with the Zuplo Developer API directly.
Never call the Zuplo Developer API directly from the browser. The API requires a
Zuplo API key (a Bearer token) that grants full management access to your
account's consumers and keys. Exposing it client-side would allow anyone to
create, delete, or read keys for any consumer.
Your backend acts as the security boundary. It verifies the user's identity using your own authentication (session cookie, JWT, etc.), determines which Zuplo consumer they map to, and proxies only the operations they are authorized to perform.
Prerequisites
Before you start, you need:
- A Zuplo project with the API Key Authentication policy configured on your routes.
- A Zuplo API key for the Developer API. Create one in the Zuplo Portal under Settings > Zuplo API Keys. More information.
- Your account name and bucket name. A bucket groups consumers for an environment — each project has buckets for production, preview, and development. Find these in the Zuplo Portal under Settings > General.
- An application with server-side code and existing user authentication.
All examples in this guide use these environment variables:
Code
Mapping users to consumers
A Zuplo consumer represents the identity behind one or more API keys. When a user in your application needs API access, you create a consumer for them in Zuplo.
The consumer's name must be unique within the bucket and is used as
request.user.sub when their key authenticates a request. A good pattern is to
use a stable identifier from your system, such as org_123 or user_456.
Use tags to link the consumer back to your internal data. Tags are key-value
pairs that you can filter on when listing or mutating consumers. For example,
storing orgId as a tag lets you scope every API call to a specific
organization, which is critical for multi-tenant security.
Use metadata to store information that should be available at runtime when
the key is used. This populates request.user.data and is commonly used for
plan tiers, customer IDs, and feature flags.
Automating consumer creation on signup
Rather than requiring users to manually request API access, create a Zuplo consumer as part of your signup or onboarding flow. When a new organization or user is created in your system, make a server-side call to create the consumer with the appropriate metadata and tags.
Creating a consumer with a name that already exists returns a 409 Conflict,
so your backend should catch this response for retry safety (for example,
treating 409 as a success if the consumer already belongs to the same user).
If a consumer does not exist yet and you attempt to list its keys, the API
returns a 404 Not Found. Make sure your onboarding flow creates the consumer
before your frontend tries to fetch keys.
This is also the right place to sync billing information. For example, if a user upgrades their plan, update the consumer's metadata so that downstream policies and handlers see the new plan on the next authenticated request.
Core operations
The following operations cover what most self-serve integrations need. Each section shows the API call your backend should make.
Consumers and API keys are subject to service limits. See API Key Service Limits for current maximums.
Create a consumer with an API key
When a user requests API access for the first time, create a consumer and an
initial API key in a single call by passing ?with-api-key=true:
Code
The response includes the consumer and an apiKeys array with the generated
key:
Code
In production, include tags on every consumer you create and pass tag.* query
parameters on every API call. This ensures proper ownership scoping. See
Secure with tags below for details.
Display the key value to the user in your UI. Although Zuplo keys are
retrievable, the standard UX pattern is to show the full key at creation time
and display it masked on subsequent views.
List a consumer's API keys
To render an "API Keys" page in your settings, fetch the consumer's keys:
Code
The key-format parameter controls how the key value appears in the response:
masked— returns a partially redacted key (e.g.,zpka_d67b...xxxx_2efbxxxx). Use this for the default list view.visible— returns the full key. Use this behind a "Reveal" button.none— omits the key value entirely. Use this when you only need key metadata (ID, dates, expiration).
The response:
Code
Create an additional API key
If a consumer needs more than one active key (for example, separate keys for staging and production), create a key directly:
Code
Rotate a key
Key rotation creates a new key and sets an expiration on existing keys, giving the user a transition period to switch over. Use the roll-key endpoint:
Code
This sets expiresOn on all existing non-expired keys for that consumer and
creates a new key with no expiration. If expiresOn is set to a date in the
past, existing keys expire immediately — effectively an instant revocation with
a new replacement key. In your UI, surface the transition period clearly — for
example: "Your current key will remain active until April 19. Update your
integration to use the new key before then."
For guidance on choosing transition period lengths, see choosing a transition period.
Delete a key
To let users revoke a specific key immediately:
Code
Key deletion is immediate and irreversible. Any request using that key will
start receiving 401 Unauthorized responses as soon as the edge cache expires
(within cacheTtlSeconds, default 60
seconds). Surface a confirmation dialog in your UI before calling this endpoint.
Update consumer metadata
When a user's plan changes or you need to update the information available at runtime, patch the consumer:
Code
The updated metadata is available on the next request that authenticates with any of that consumer's keys (subject to cache TTL).
Secure with tags
Tags are the primary mechanism for enforcing ownership in multi-tenant
integrations. Most Zuplo Developer API endpoints accept tag.* query parameters
that filter results and — critically — reject the request if the tag does not
match.
For example, if your backend knows the authenticated user belongs to org_123,
append ?tag.orgId=org_123 to every call:
Code
This prevents one user from operating on another user's consumers, even if they somehow obtain a valid consumer name. Your backend should always derive the tag value from the authenticated session — never from the request body or query string sent by the frontend.
Backend implementation example
Here is a minimal Express.js example showing how to proxy key operations through your backend. Adapt this pattern to your framework and language.
Code
This example omits error handling for brevity. In production, handle these key
error responses from the Zuplo Developer API: 404 (consumer or key not found),
409 (consumer name already exists), and 429 (rate limited). See the
Zuplo Developer API documentation for full
details on error responses.
Integration options
Depending on how much control you need, there are several ways to integrate:
| Approach | Effort | Control | Best for |
|---|---|---|---|
| Zuplo Developer Portal | None | Low | Teams that don't need a custom UI |
| Custom UI with the Developer API (this guide) | Medium | Full | Any stack, full control over UX |
Next steps
- API Key API reference — additional API operations including querying consumers by tags and bulk key creation.
- Zuplo Developer API documentation — full endpoint reference for all consumer, key, bucket, and manager operations.
- API Key Authentication policy — configure how keys are validated on your routes.