SuperAgent API
Per-endpoint limits
Limits stop one key or worker from using more capacity than you intended. You can answer four separate questions for each endpoint:
- How many requests can it make per minute, hour, or day?
- How many requests can run at the same time?
- How many Agent Credits can selected money operations spend per day?
- Should a broad key-wide limit also apply?
Limits are fixed when the key is created. Create a replacement key when you need different limits.
const result = await hive.apiKeys.create(
{
label: "Bounded worker",
scopes: [
"services:read",
"services:invoke",
"wallets:read",
"wallets:transact",
],
allowedServices: ["hive-research", "managed-wallets"],
limits: {
"*": {
requestsPerHour: 2_000,
maxConcurrent: 20,
},
"services.invoke": {
requestsPerMinute: 120,
},
"services.invoke.hive-research": {
requestsPerMinute: 30,
maxConcurrent: 3,
},
"services.invoke.hive-research.analyses.create": {
requestsPerDay: 250,
},
"services.invoke.cloud-superbrain.memory.answer": {
requestsPerMinute: 10,
requestsPerDay: 500,
},
"wallets.transactions.create": {
requestsPerDay: 10,
creditsPerDay: 25,
},
"credits.x402.topUp": {
requestsPerDay: 4,
},
},
},
{ idempotencyKey: "bounded-worker-v1" },
);
Advanced: selector matching and validation ceilings
Limit selectors
The limits object is keyed by an operation id:
| Selector | Applies to |
|---|---|
* |
Every authenticated SuperAgent API operation. |
A static operation such as databases.actions |
Only that endpoint operation. |
services.invoke |
Every direct managed-service invocation. |
services.invoke.<serviceId> |
Direct invocation of one managed service. |
services.invoke.<serviceId>.<operationId> |
One exact registered capability invoked directly. |
runs.create |
Every durable run creation. |
runs.create.<serviceId> |
Run creation for one managed service. |
runs.create.<serviceId>.<operationId> |
One exact registered capability created as a run. |
For hive-research operation analyses.create, the API checks *, services.invoke, services.invoke.hive-research, and services.invoke.hive-research.analyses.create. Every matching limit applies. The request is rejected as soon as any one of them is exhausted.
The same hierarchy applies to managed memory. An answer call can be limited independently with services.invoke.cloud-superbrain.memory.answer, while services.invoke.cloud-superbrain caps every Cloud Superbrain operation available to that key.
The complete set of accepted operation ids is exported as HIVEMINDOS_PLATFORM_OPERATION_IDS by the TypeScript SDK and appears in the endpoint reference.
Limit fields
| Field | Meaning | Accepted maximum |
|---|---|---|
requestsPerMinute |
Requests during a fixed minute window. | 60,000 |
requestsPerHour |
Requests during a fixed hour window. | 1,000,000 |
requestsPerDay |
Requests during a fixed UTC day. | 10,000,000 |
maxConcurrent |
Requests for the selector that may be in progress at once. | 1,000 |
creditsPerDay |
HivemindOS credits charged by one supported operation during a fixed UTC day. | 1,000,000,000 |
Request and concurrency values must be positive integers. creditsPerDay must be positive and may have at most three decimal places. A key may define at most 128 operation selectors.
These are validation ceilings, not automatic quotas. If a field is omitted, that key does not add a limit for that field. Account balance, plan allowance, service availability, wallet policy, and any ancestor-key limits still apply.
Concurrent capacity remains in use until the response finishes, including a streamed response. Always consume or cancel response bodies so your application releases capacity promptly.
Daily credit limits
creditsPerDay is available only for SuperAgent API-billed operations whose maximum charge can be checked before work starts:
wallets.createwallets.transactions.createwallets.signatures.createtrading.orders.create
Daily credit limits cannot be placed on *, a managed-service selector, a quote, a read, or another operation. Before a supported paid action starts, the API confirms that its maximum charge fits the remaining key limit. Only the final charged amount counts toward the daily total.
credits.x402.topUp accepts request and concurrency limits, but not creditsPerDay: it buys credits rather than spending them. The unsigned HTTP 402 challenge does not consume the top-up request window. The first signed payment attempt does, while a completed idempotent replay returns the saved result without consuming another slot.
A key-level credit limit does not add credits to the account and does not replace wallet policy. A request must pass the key limit, have enough account credits, and satisfy the wallet’s own transaction and daily rules.
Delegated keys and ancestor limits
Every key in the authority chain remains active policy. If a root key allows 1,000 requests per hour and a child allows 100, the child’s effective ceiling is 100. A child cannot create a covering limit with a larger value than an ancestor.
Omitting a child limit does not bypass its parent. Revoking or expiring any ancestor invalidates the child entirely.
Use this to enforce organizational ceilings at the root while allowing each worker to set a smaller local budget.
Handle HTTP 429
When a key reaches a request, concurrency, or supported daily-credit limit, the API returns HTTP 429:
{
"ok": false,
"code": "rate_limit_exceeded",
"error": "This API key has reached its request limit for this operation.",
"operationId": "services.invoke.hive-research",
"metric": "requestsPerMinute",
"retryAfterSeconds": 18
}
The response also includes:
Retry-After: 18
X-HivemindOS-Limit-Operation: services.invoke.hive-research
Pause that workload for at least retryAfterSeconds. Queueing work in your own backend is usually better than making every caller retry independently. A different operation may still have capacity, but do not route around a deliberate key-wide or ancestor limit.
const result = await hive.services.invokeOperation(
"hive-research",
"analyses.create",
{ question: "..." },
{ idempotencyKey: jobId },
);
if (!result.ok && result.code === "rate_limit_exceeded") {
await queueForLater(jobId, result.retryAfterSeconds ?? 60);
}
Next: review authentication and delegation or find an exact selector in the endpoint reference.