List your team's plan limits and feature flags. Entitlements are enforced when you create API keys, connectors, knowledge bases, private apps, upload files, or run tasks.
Use GET /entitlements to see entitlement rows (limits and sources). Use GET /entitlements/usage to see current usage vs limits.
List entitlements
GET /entitlements
Returns all entitlement rows for the API key's team. Requires a valid API key (any scope).
Example:
1curl https://api.inference.sh/entitlements \2 -H "Authorization: Bearer inf_your_key" \3 -H "X-API-Version: 2"Response (array of entitlement objects):
1[2 {3 "id": "ent_abc123",4 "team_id": "team_xyz",5 "resource": "api_keys",6 "type": "limit",7 "enabled": true,8 "unlimited": false,9 "limit": 5,10 "source": "tier",11 "enforcement": "block"12 }13]Fields
| Field | Type | Description |
|---|---|---|
resource | string | What is limited — see Resources below |
type | string | Entitlement type from the plan definition |
enabled | boolean | Whether the resource or feature is enabled |
unlimited | boolean | When true, no numeric cap applies |
limit | number | Maximum allowed (when not unlimited) |
source | string | Origin: tier, addon, trial, whitelist, or override |
enforcement | string | block (hard deny when exceeded) or warn (allow with warning) |
expires_at | string | ISO timestamp when a trial or override expires (optional) |
When multiple rows exist for the same resource, the API resolves the highest-priority source: override > whitelist > trial > tier / addon. Rows from tier and addon are merged for the same resource — boolean features use OR, numeric limits are summed, and any unlimited row makes the merged result unlimited.
Get usage
GET /entitlements/usage
Returns current usage vs limits for countable resources, inflight task concurrency, and boolean feature gates. Requires a valid API key (any scope).
Unlike GET /entitlements, this endpoint includes live usage counts — for example how many API keys exist, how much storage is used, and how many tasks are currently in flight.
Example:
1curl https://api.inference.sh/entitlements/usage \2 -H "Authorization: Bearer inf_your_key" \3 -H "X-API-Version: 2"Response (array of usage objects):
1[2 {3 "resource": "api_keys",4 "label": "api keys",5 "type": "limit",6 "usage": 3,7 "limit": 5,8 "unlimited": false9 },10 {11 "resource": "storage_mb",12 "label": "storage",13 "type": "limit",14 "unit": "mb",15 "usage": 128,16 "limit": 1024,17 "unlimited": false18 },19 {20 "resource": "concurrency",21 "label": "concurrent tasks",22 "type": "limit",23 "usage": 2,24 "limit": 3,25 "unlimited": false26 },27 {28 "resource": "feature:webhooks",29 "label": "webhooks",30 "type": "boolean",31 "enabled": true32 },33 {34 "resource": "feature:seedance",35 "label": "seedance video generation",36 "type": "boolean",37 "enabled": false38 }39]Usage fields
| Field | Type | Description |
|---|---|---|
resource | string | Resource identifier (same values as Resources) |
label | string | Human-readable name (for example concurrent tasks, api keys) |
unit | string | Display unit from the plan (for example mb, days) — optional |
type | string | limit (numeric cap) or boolean (feature gate) |
usage | number | Current usage (limit-type resources only) |
limit | number | Maximum allowed when not unlimited (limit-type only) |
unlimited | boolean | When true, no numeric cap applies (limit-type only) |
enabled | boolean | Whether the feature is enabled (boolean-type only) |
When no entitlement row exists for a limit-type resource, the response sets unlimited: true and still returns the current usage.
What is counted
| Resource | Usage source |
|---|---|
api_keys | Number of API keys for the team |
storage_mb | Total uploaded file storage in megabytes |
seats | Number of team members |
triggers | Trigger subscriptions linked to agents |
concurrency | Inflight tasks — queued (received, queued) plus in-progress (dispatched, preparing, serving, setting_up, running, cancelling, uploading) |
Boolean features (for example feature:webhooks, feature:byok, feature:seedance) appear only when an entitlement row exists for that feature.
In the workspace, Settings → Subscription shows the same usage rows with progress bars — yellow at 80% of a finite limit, orange at the cap.
Resources
Common resource values returned by GET /entitlements:
| Resource | Typical use |
|---|---|
api_keys | Number of API keys |
connectors | MCP connectors |
knowledge_bases | Knowledge entries |
private_apps | Private app deployments |
storage_mb | Total uploaded file storage |
task_executions | Task runs per billing period |
concurrency | Concurrent tasks (inflight runs) |
rate_per_min | API rate per minute |
seats | Team members |
triggers | Agent trigger subscriptions (event, schedule, or manual) |
retention_days | Data retention period in days (plan policy; not usage-counted) |
feature:scopes | Custom API key scopes |
feature:webhooks | Webhooks |
feature:byok | Bring your own keys |
feature:seedance | Seedance video generation |
feature:publish_apps | Publishing apps to the store |
feature:auto_recharge | Auto-recharge billing |
feature:invoices | Invoice billing |
feature:team_billing | Team billing features |
Limit vs feature gate semantics
How the API treats a missing entitlement row depends on the resource type and where it is checked:
| Context | No entitlement row | Row with enabled: false |
|---|---|---|
limit resources (for example api_keys, concurrency) | No restriction — GET /entitlements/usage reports unlimited: true | Uses limit / unlimited, not enabled |
boolean plan features (standard entitlement checks) | No restriction | Feature blocked |
Store app required_feature | Denied — explicit grant required | Denied |
Capacity limits follow an opt-out model: no row means no cap. Store app feature gates follow an opt-in model: your team must have a boolean entitlement row with enabled: true for the listed required_feature. A missing row is not treated as unrestricted access.
When limits block a request
Hard-blocked entitlements return API errors before the operation completes:
| Code | HTTP | Meaning |
|---|---|---|
limit_exceeded | 402 | Numeric limit reached |
feature_not_available | 403 | Boolean feature disabled on your tier |
payment_required | 402 | Insufficient prepaid balance (separate from plan limits) |
Error metadata
When a plan limit blocks a request, structured metadata is attached to the error response. Clients that drive upgrade flows (the workspace app, belt CLI) read these fields from the raw response body.
| Field | Description |
|---|---|
resource | Resource identifier (for example api_keys, concurrency) |
resource_label | Human-readable label (for example concurrent tasks) |
limit | Plan limit that was exceeded |
current | Usage at the time of the request |
upgrade_available | Always true for entitlement errors — the CLI appends an upgrade URL; the workspace opens the upgrade modal |
addon_plan_id | Optional — plan ID for an addon that unlocks the blocked feature (present when a store app requires a purchasable addon) |
addon_plan_name | Optional — display name of the addon plan |
addon_plan_price | Optional — monthly price in cents for the addon plan |
Version 1 (default, no X-API-Version header) — metadata is nested under error.meta:
1{2 "success": false,3 "status": 402,4 "error": {5 "code": "limit_exceeded",6 "message": "You have reached the limit of 3 concurrent tasks",7 "meta": {8 "resource": "concurrency",9 "resource_label": "concurrent tasks",10 "limit": 3,11 "current": 3,12 "upgrade_available": true13 }14 }15}When a store app blocks on a purchasable addon (for example feature:seedance), error.meta may also include addon fields:
1{2 "success": false,3 "status": 403,4 "error": {5 "code": "feature_not_available",6 "message": "this app requires the seedance video generation add-on.",7 "meta": {8 "resource": "feature:seedance",9 "resource_label": "seedance video generation",10 "upgrade_available": true,11 "addon_plan_id": "plan_seedance_addon",12 "addon_plan_name": "Seedance",13 "addon_plan_price": 99914 }15 }16}Version 2 (X-API-Version: 2) — returns RFC 9457 application/problem+json with a human-readable detail and the same metadata fields under a top-level meta extension member (RFC 9457 allows extension members on problem details):
1{2 "type": "https://api.inference.sh/errors/limit_exceeded",3 "title": "Payment Required",4 "status": 402,5 "detail": "You have reached the limit of 3 concurrent tasks",6 "meta": {7 "resource": "concurrency",8 "resource_label": "concurrent tasks",9 "limit": 3,10 "current": 3,11 "upgrade_available": true12 }13}When a store app blocks on a purchasable addon, the version 2 meta object includes the same addon fields as version 1:
1{2 "type": "https://api.inference.sh/errors/feature_not_available",3 "title": "Forbidden",4 "status": 403,5 "detail": "this app requires the seedance video generation add-on.",6 "meta": {7 "resource": "feature:seedance",8 "resource_label": "seedance video generation",9 "upgrade_available": true,10 "addon_plan_id": "plan_seedance_addon",11 "addon_plan_name": "Seedance",12 "addon_plan_price": 99913 }14}Official SDKs expose the raw problem body on APIError.response_body (Python) or InferenceError.responseBody (JavaScript) — parse meta from the JSON when you need structured entitlement fields. The belt / infsh CLI sends X-API-Version: 2 and checks meta.upgrade_available on problem+json responses (or error.meta.upgrade_available on legacy version 1 envelopes) to append an upgrade URL to the error message. When addon_plan_id is present, the URL points to Settings → Billing → Add-ons; otherwise it points to the subscription page. You can also inspect limits proactively with GET /entitlements/usage.
Workspace upgrade modal
When a workspace API call returns limit_exceeded or feature_not_available with upgrade_available: true, the app opens the upgrade modal and passes error metadata (resource, resource_label, limit, current, and detail). The modal lists self-serve plans above your current tier and highlights the recommended plan — the cheapest tier that lifts the blocked resource. For numeric limits it shows current / limit only when limit is greater than zero.
When addon_plan_id is present (for example a blocked feature:seedance run on a store app), the workspace shows an add-on purchase modal instead of a tier upgrade — with the addon name and monthly price from addon_plan_name and addon_plan_price. The primary CTA reads subscribe - $X/mo and routes to Settings → Billing → Add-ons to complete checkout (same flow as the add-ons page cards). Most add-ons do not require a base subscription; some set required_plan_ids on the plan (see Subscription API — Add-on subscriptions).
Feature-gated store apps
Some store apps declare a required_feature on their listing (for example feature:seedance). Before dispatch, the API resolves that entitlement for your team and requires an explicit grant: a boolean row with enabled: true. If no row exists, or the row has enabled: false, task dispatch returns feature_not_available (403) before the run starts.
This is stricter than capacity limits, where a missing row means no restriction. For gated store apps, access is denied unless the feature is positively enabled on your team.
Check GET /entitlements/usage for boolean feature status, or inspect required_feature on GET /store/apps/{appId}. See Store API — Get app store listing.
See REST overview — Billing and plan limits for modal behavior, workspace links, and credit balance errors.
Related
- REST overview — authentication and API versioning
- Tasks API — run apps (may return
payment_required) - Troubleshooting — common limit and balance errors