Zuplo API v4
Zuplo Developer API

A user app gives every person in the account their own personal API keys and personal budget for the AI Gateway. That covers coding agents like Claude Code or Cursor, scripts, and notebooks. Its policies work like an app's, and its metering policy's per-person rule (budgetBy: expression on request.user.sub) sets the limits every person gets.

Every gateway has exactly one user app, created with the gateway. It is listed, read and changed, but never created or deleted.

Everything about one person in the user app is under …/ai/user-apps/{userAppId}/users/{userId}:

  • consumers: their API keys, for example one consumer per laptop,
  • budget: their own limits, which replace the per-person defaults, for example a higher daily spend for one engineer,
  • usage: their current usage against their limits.

…/users lists the people who can use the user app. A person has no ID of their own in it: they are identified by the user app and their userId.

People who can edit the user app are its admins. Everyone who can use the user app manages their own consumers and keys, and reads their own budget and usage, with their own userId. Admins can do the same for anyone: issue each person a key, one request per person, revoke it, see their usage, and set their budget.


List user apps

GET
https://dev-api-v4-main-a471234.zuplo.app
/v4/buckets/{bucketId}/ai/user-apps

Lists the gateway's user apps. Every gateway has exactly one, created with the gateway.

List user apps › path Parameters

bucketId
​string · maxLength: 64 · required

The bucket ID (bckt_…). Everything in a bucket is addressed under it.

List user apps › query Parameters

limit
​integer · min: 1 · max: 100

The maximum number of items to return.

Default: 10
offset
​integer · min: 0

The number of items to skip before the first item returned.

Default: 0

List user apps › Responses

A page of user apps.

A page of user apps.
​AiUserApp[] · required

The user apps on this page.

limit
​integer · required

The page size that was applied.

offset
​integer · required

The number of items skipped before this page.

total
​integer · required

The number of items in the whole collection.

hasMore
​boolean · required

Whether there are more items after this page.

next
​string | null · required

The relative URL of the next page, or null on the last page.


Get a user app

GET
https://dev-api-v4-main-a471234.zuplo.app
/v4/buckets/{bucketId}/ai/user-apps/{userAppId}

Returns a user app and its policies, which set everyone's personal limits.

Get a user app › path Parameters

bucketId
​string · maxLength: 64 · required

The bucket ID (bckt_…). Everything in a bucket is addressed under it.

userAppId
​string · maxLength: 64 · required

The user app ID (config_…).

Get a user app › Responses

The user app.

Personal API keys and per-person budgets for everyone in the account.
id
​string · required

The user app ID.

Example: config_UsTroIp2e0K8mWYGj1GT8U13
bucketId
​string · required

The bucket (gateway) the user app belongs to.

Example: bckt_Y40ypGODCDP3S7iZxNwCAbIe
name
​string · required

The user app's display name.

Example: Personal keys
baseUrl
​string | null · uri · required

Where personal-key clients (Claude Code, Cursor, scripts) send requests. Null until the gateway is deployed.

Example: https://acme-ai-gateway-main-b8e2f1a.zuplo.app/u/UsTroIp2e0K8mWYGj1GT8U13
​AiPolicy[] · required

The policies every personal-key request runs, in order. The metering policy's per-person rule (budgetBy: expression on request.user.sub) sets the limits every person gets. A person's budget changes them for that person.

createdOn
​string · date-time · required

When the user app was created.

updatedOn
​string · date-time · required

When the user app was last changed.


Update a user app

PATCH
https://dev-api-v4-main-a471234.zuplo.app
/v4/buckets/{bucketId}/ai/user-apps/{userAppId}

Updates a user app with JSON Merge Patch semantics. policies is replaced as a whole. Changing the metering policy's per-person rule changes the limits of everyone without limits of their own. Fails with 409 when it removes a limit that a person's budget still changes.

Update a user app › path Parameters

bucketId
​string · maxLength: 64 · required

The bucket ID (bckt_…). Everything in a bucket is addressed under it.

userAppId
​string · maxLength: 64 · required

The user app ID (config_…).

Update a user app › Request Body

Changes to a user app (JSON Merge Patch).
name
​string · minLength: 1 · maxLength: 128

The user app's display name.

​AiPolicyInput[] · maxItems: 30

Replaces all of the user app's policies, in the order they run. Keep the metering policy's per-person rule to keep personal limits: removing a limit that a person's budget still changes fails with 409.

Update a user app › Responses

The updated user app.

Personal API keys and per-person budgets for everyone in the account.
id
​string · required

The user app ID.

Example: config_UsTroIp2e0K8mWYGj1GT8U13
bucketId
​string · required

The bucket (gateway) the user app belongs to.

Example: bckt_Y40ypGODCDP3S7iZxNwCAbIe
name
​string · required

The user app's display name.

Example: Personal keys
baseUrl
​string | null · uri · required

Where personal-key clients (Claude Code, Cursor, scripts) send requests. Null until the gateway is deployed.

Example: https://acme-ai-gateway-main-b8e2f1a.zuplo.app/u/UsTroIp2e0K8mWYGj1GT8U13
​AiPolicy[] · required

The policies every personal-key request runs, in order. The metering policy's per-person rule (budgetBy: expression on request.user.sub) sets the limits every person gets. A person's budget changes them for that person.

createdOn
​string · date-time · required

When the user app was created.

updatedOn
​string · date-time · required

When the user app was last changed.


List the people in a user app

GET
https://dev-api-v4-main-a471234.zuplo.app
/v4/buckets/{bucketId}/ai/user-apps/{userAppId}/users

Lists the people who can use the user app, by email address. Add include[]=budget for each person's budget. Filter by hasBudgetOverride to see who has limits of their own. User app admins see everyone. Everyone else sees only themselves.

List the people in a user app › path Parameters

bucketId
​string · maxLength: 64 · required

The bucket ID (bckt_…). Everything in a bucket is addressed under it.

userAppId
​string · maxLength: 64 · required

The user app ID (config_…).

List the people in a user app › query Parameters

hasBudgetOverride
​boolean

Only return the people who have limits of their own (true), or only those on the defaults (false).

include[]
​string[] · maxItems: 1 · unique · style: form · explode: true

What else to return with each person. budget returns their limits, as …/users/{userId}/budget does, in budget, which is null otherwise.

Enum values:
budget
limit
​integer · min: 1 · max: 100

The maximum number of items to return.

Default: 10
offset
​integer · min: 0

The number of items to skip before the first item returned.

Default: 0

List the people in a user app › Responses

A page of the people in the user app.

A page of the people in a user app.
​AiUserAppUser[] · required

The people on this page.

limit
​integer · required

The page size that was applied.

offset
​integer · required

The number of items skipped before this page.

total
​integer · required

The number of items in the whole collection.

hasMore
​boolean · required

Whether there are more items after this page.

next
​string | null · required

The relative URL of the next page, or null on the last page.


Get a person in a user app

GET
https://dev-api-v4-main-a471234.zuplo.app
/v4/buckets/{bucketId}/ai/user-apps/{userAppId}/users/{userId}

Returns one person who can use the user app, and with include[]=budget their budget. Their budget, usage and consumers are under this URL, where the budget is also set. 404 when the person cannot use the user app.

Get a person in a user app › path Parameters

bucketId
​string · maxLength: 64 · required

The bucket ID (bckt_…). Everything in a bucket is addressed under it.

userAppId
​string · maxLength: 64 · required

The user app ID (config_…).

userId
​UserId · maxLength: 64 · required

The user ID of an account member (user_…).

A person, identified by their Zuplo user ID (user_…). Zuplo assigns it when the person is first added to an account, before they ever sign in, and it never changes. Every userId and ownerId in v4 is one.

Example: user_Jm5tR8wQz2KcX7vB4nLp9HdS

Get a person in a user app › query Parameters

include[]
​string[] · maxItems: 1 · unique · style: form · explode: true

What else to return with each person. budget returns their limits, as …/users/{userId}/budget does, in budget, which is null otherwise.

Enum values:
budget

Get a person in a user app › Responses

The person.

A person who can use a user app, and with `include[]=budget` their `budget` as `GET …/users/{userId}/budget` returns it. The budget is read-only here: set it with `PUT …/users/{userId}/budget`.
userAppId
​string · required

The user app.

Example: config_UsTroIp2e0K8mWYGj1GT8U13
userId
​UserId · maxLength: 64 · required

A person, identified by their Zuplo user ID (user_…). Zuplo assigns it when the person is first added to an account, before they ever sign in, and it never changes. Every userId and ownerId in v4 is one.

Example: user_Jm5tR8wQz2KcX7vB4nLp9HdS
email
​string · email · required

The person's email address.

name
​string | null · required

The person's display name, if they set one.

hasBudgetOverride
​boolean · required

Whether the person has limits of their own (…/users/{userId}/budget) instead of the user app's defaults.

​required

The person's limits, as GET …/users/{userId}/budget returns them. Null unless include[] has budget.


Get a person's budget

GET
https://dev-api-v4-main-a471234.zuplo.app
/v4/buckets/{bucketId}/ai/user-apps/{userAppId}/users/{userId}/budget

Returns one person's own limits in the user app, which replace the user app's per-person defaults. limits is empty when the defaults apply. People read their own. User app admins can read anyone's.

Get a person's budget › path Parameters

bucketId
​string · maxLength: 64 · required

The bucket ID (bckt_…). Everything in a bucket is addressed under it.

userAppId
​string · maxLength: 64 · required

The user app ID (config_…).

userId
​UserId · maxLength: 64 · required

The user ID of an account member (user_…).

A person, identified by their Zuplo user ID (user_…). Zuplo assigns it when the person is first added to an account, before they ever sign in, and it never changes. Every userId and ownerId in v4 is one.

Example: user_Jm5tR8wQz2KcX7vB4nLp9HdS

Get a person's budget › Responses

The person's budget.

One person's own limits in a user app, which replace the user app's per-person defaults.
userAppId
​string · required

The user app.

Example: config_UsTroIp2e0K8mWYGj1GT8U13
userId
​UserId · maxLength: 64 · required

A person, identified by their Zuplo user ID (user_…). Zuplo assigns it when the person is first added to an account, before they ever sign in, and it never changes. Every userId and ownerId in v4 is one.

Example: user_Jm5tR8wQz2KcX7vB4nLp9HdS
​BudgetLimit[] · required

The person's own limits. Empty when the defaults apply. Limits that are not listed keep the defaults.

updatedOn
​string | null · date-time · required

When the limits were last set, or null if they never were.


Set a person's budget

PUT
https://dev-api-v4-main-a471234.zuplo.app
/v4/buckets/{bucketId}/ai/user-apps/{userAppId}/users/{userId}/budget

Sets one person's own limits, replacing the ones they had, so sending the same request again changes nothing. Send the complete list. limits: [] puts the person back on the user app's defaults. Only cost limits with action block that exist in the user app's per-person budget rule can be set, and only user app admins can set them.

Returns 201 when the person had no limits of their own and now has, and 200 otherwise. Fails with 409 when the gateway's budget rules, not the user app, hold the per-person rule.

Set a person's budget › path Parameters

bucketId
​string · maxLength: 64 · required

The bucket ID (bckt_…). Everything in a bucket is addressed under it.

userAppId
​string · maxLength: 64 · required

The user app ID (config_…).

userId
​UserId · maxLength: 64 · required

The user ID of an account member (user_…).

A person, identified by their Zuplo user ID (user_…). Zuplo assigns it when the person is first added to an account, before they ever sign in, and it never changes. Every userId and ownerId in v4 is one.

Example: user_Jm5tR8wQz2KcX7vB4nLp9HdS

Set a person's budget › Request Body

One person's own limits. The person is the `userId` in the path.
​BudgetLimitInput[] · maxItems: 4 · required

Replaces the person's own limits. Each must match a cost limit with action block in the user app's per-person budget rule. [] puts the person back on the defaults.

Set a person's budget › Responses

The person's limits were replaced.

One person's own limits in a user app, which replace the user app's per-person defaults.
userAppId
​string · required

The user app.

Example: config_UsTroIp2e0K8mWYGj1GT8U13
userId
​UserId · maxLength: 64 · required

A person, identified by their Zuplo user ID (user_…). Zuplo assigns it when the person is first added to an account, before they ever sign in, and it never changes. Every userId and ownerId in v4 is one.

Example: user_Jm5tR8wQz2KcX7vB4nLp9HdS
​BudgetLimit[] · required

The person's own limits. Empty when the defaults apply. Limits that are not listed keep the defaults.

updatedOn
​string | null · date-time · required

When the limits were last set, or null if they never were.


Get a person's usage

GET
https://dev-api-v4-main-a471234.zuplo.app
/v4/buckets/{bucketId}/ai/user-apps/{userAppId}/users/{userId}/usage

Returns one person's current usage against their limits. People read their own. User app admins can read anyone's.

Get a person's usage › path Parameters

bucketId
​string · maxLength: 64 · required

The bucket ID (bckt_…). Everything in a bucket is addressed under it.

userAppId
​string · maxLength: 64 · required

The user app ID (config_…).

userId
​UserId · maxLength: 64 · required

The user ID of an account member (user_…).

A person, identified by their Zuplo user ID (user_…). Zuplo assigns it when the person is first added to an account, before they ever sign in, and it never changes. Every userId and ownerId in v4 is one.

Example: user_Jm5tR8wQz2KcX7vB4nLp9HdS

Get a person's usage › Responses

The person's usage.

One person's usage against their personal limits.
userAppId
​string · required

The user app.

Example: config_UsTroIp2e0K8mWYGj1GT8U13
userId
​UserId · maxLength: 64 · required

A person, identified by their Zuplo user ID (user_…). Zuplo assigns it when the person is first added to an account, before they ever sign in, and it never changes. Every userId and ownerId in v4 is one.

Example: user_Jm5tR8wQz2KcX7vB4nLp9HdS
​AiUsageLimit[] · required

Usage per limit.

measuredOn
​string · date-time · required

How fresh the numbers are. Usage is aggregated asynchronously and can lag by a few seconds.