Consumers
A consumer represents one of your customers and owns a single credit pool shared by all of its keys. This is where credits — and rate limits — live.
/consumer/createBearerCreate consumer
Consumers own credits. Configure credits three ways, in priority order: direct credits object > plan inheritance (planId) > nothing (unlimited). Every key you create under this consumer draws from the same pool. A consumer can also carry a rateLimit that caps how fast all of its keys can call /key/validate.
namestringConsumer name.
creditsobjectDirect credit configuration (takes priority over plan).
limitnumberTotal credit limit (pool size).
shadowLimitnumberWarning threshold before the hard limit.
refillobjectAuto-refill: { interval, amount }.
overageobjectOverage: { enabled, limit }.
expiresAtnumberCredit expiration timestamp (ms).
planIdstringInherit credits from a plan (used only if credits is omitted).
rateLimitobjectRequest rate limit shared by all the consumer’s keys: limit /key/validate requests per window seconds.
limitnumberrequiredMax requests per window. 1 – 1,000,000,000.
windownumberWindow length in seconds, 1 – 86,400. Default 1. E.g. 100/minute is { limit: 100, window: 60 }.
tagsarrayArray of string tags.
webhookUrlstringWebhook URL for notifications.
metadataobjectArbitrary custom metadata.
imageUrlstringConsumer avatar URL.
externalIdstringYour system’s identifier for this consumer.
statusstringStatus. Default "active".
curl -X POST "https://api.reqkey.com/consumer/create" \
-H "Authorization: Bearer reqkey_xxx..." \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Corporation",
"credits": {
"limit": 5000,
"shadowLimit": 500,
"overage": {
"enabled": true,
"limit": 200
}
},
"rateLimit": {
"limit": 100,
"window": 60
},
"tags": [
"enterprise",
"priority"
],
"externalId": "acme_12345"
}'{
"consumerId": "cons_A1B2C3D4",
"projectKey": "reqkey_xxx...",
"createdAt": "2026-01-30T12:34:56Z",
"status": "active",
"name": "Acme Corporation",
"tags": [
"enterprise",
"priority"
],
"externalId": "acme_12345"
}- Omit both credits and planId to give the consumer (and all its keys) unlimited usage.
- The rate limit is independent of credits — a consumer with unlimited credits can still be rate-limited.
- If you pass planId and no explicit rateLimit, the consumer inherits the plan’s rate limit; an explicit rateLimit in the same request wins.
- The consumer is added to the project:{rootKey}:consumers set.
/consumer/updateBearerUpdate consumer
Update any consumer field, including credits and rateLimit. Consumer status doubles as a master switch: set it to "disabled" and every key under the consumer stops validating without touching each key’s own status — ideal for payment failures.
consumerIdstringrequiredConsumer ID to update.
namestringNew consumer name.
statusstringNew status (e.g. "active", "disabled").
planIdstringNew plan ID.
tagsarrayNew tags array.
metadataobjectNew metadata object.
webhookUrlstringNew webhook URL.
imageUrlstringNew image URL.
externalIdstringNew external ID.
expiresAtstringExpiration timestamp.
creditsobjectUpdate credit configuration.
limitnumberNew credit limit (pool size).
usednumberSet the used count — handy for plan downgrades (reset to 0 for a fresh pool).
shadowLimitnumberWarning threshold.
overageobjectOverage config: { enabled, limit }.
refillobjectAuto-refill config.
expiresAtnumberCredit expiration timestamp (ms).
rateLimitobject | nullNew rate limit for the consumer, or null to remove it entirely.
limitnumberrequiredMax /key/validate requests per window. 1 – 1,000,000,000.
windownumberWindow length in seconds, 1 – 86,400. Default 1.
curl -X POST "https://api.reqkey.com/consumer/update" \
-H "Authorization: Bearer reqkey_xxx..." \
-H "Content-Type: application/json" \
-d '{
"consumerId": "cons_A1B2C3D4",
"credits": {
"limit": 10000,
"shadowLimit": 1000,
"overage": {
"enabled": true,
"limit": 500
}
},
"rateLimit": {
"limit": 100,
"window": 60
}
}'{
"consumerId": "cons_A1B2C3D4",
"name": "Acme Corporation",
"status": "active",
"credits": {
"limit": 10000,
"shadowLimit": 1000,
"overage": {
"enabled": true,
"limit": 500
}
},
"keysRestored": 0
}- Disabled consumer blocks all its keys; setting it back to "active" re-enables them instantly.
- Moving status from "deleted" to "active" restores soft-deleted keys (see keysRestored).
- Downgrading a plan? Pass credits.used: 0 alongside the new limit so remaining never goes negative.
- rateLimit: null removes the limit — even if the consumer is on a plan that has one. Re-attach the plan (or set a value) to restore it.
- Changing planId without passing rateLimit re-inherits the new plan’s rate limit; an explicit rateLimit (or null) in the same request wins. A plan with no rate limit leaves the consumer’s current limit alone.
- Rate-limit changes reach the validation hot path within ~200ms for active consumers (worst case ~30s for a consumer idle longer than 2 minutes).
/consumer/detailsBearerGet consumer details
Fetch a consumer with full credit status.
consumerIdstringrequiredConsumer ID to retrieve.
curl -X POST "https://api.reqkey.com/consumer/details" \
-H "Authorization: Bearer reqkey_xxx..." \
-H "Content-Type: application/json" \
-d '{
"consumerId": "cons_A1B2C3D4"
}'{
"consumerId": "cons_A1B2C3D4",
"projectKey": "reqkey_xxx...",
"name": "Acme Corporation",
"imageUrl": null,
"externalId": "acme_12345",
"metadata": {
"tier": "enterprise"
},
"webhookUrl": "https://acme.com/webhooks/credits",
"status": "active",
"planId": "plan_enterprise",
"tags": [
"enterprise",
"priority"
],
"createdAt": "2026-01-30T12:34:56Z",
"expiresAt": null,
"updatedAt": "2026-01-30T12:35:00Z",
"rateLimit": {
"limit": 100,
"window": 60
},
"credits": {
"limit": 10000,
"remaining": 8500,
"used": 1500,
"shadowLimit": 1000,
"overage": {
"enabled": true,
"limit": 500
},
"refill": {
"interval": "month",
"amount": 5000,
"nextRefillAt": 1743465600000
},
"expiresAt": null
}
}- credits is null when the consumer has no credit configuration (unlimited).
- rateLimit is null when no rate limit is configured.
/consumer/listBearerList consumers
Returns one page of consumers. All request fields are optional — an empty body returns the first page, newest first. Filters compose (AND): search + status + planId narrow the same result set, and the response reports both the project-wide total and the filtered count.
pagenumberPage number, 1-based. Default 1.
limitnumberPage size. Default 25, max 200.
searchstringCase-insensitive substring match on consumerId OR name.
planIdstringFilter consumers by plan ID (exact match).
statusstringFilter by status, e.g. active, deleted (exact match).
sortBystringcreatedAt (default), name, status, creditsUsed, or creditsRemaining.
sortOrderstringasc or desc. Default desc.
curl -X POST "https://api.reqkey.com/consumer/list" \
-H "Authorization: Bearer reqkey_xxx..." \
-H "Content-Type: application/json" \
-d '{
"search": "acme",
"status": "active",
"planId": "plan_enterprise",
"sortBy": "creditsRemaining",
"sortOrder": "asc",
"page": 1,
"limit": 50
}'{
"total": 1426,
"filtered": 2,
"page": 1,
"limit": 25,
"totalPages": 1,
"sortBy": "createdAt",
"sortOrder": "desc",
"consumers": [
{
"consumerId": "cons_A1B2C3D4",
"name": "Acme Corporation",
"imageUrl": "https://example.com/acme.png",
"planId": "plan_enterprise",
"createdAt": "2026-01-30T12:34:56Z",
"status": "active",
"apiKeyCount": 2,
"credits": {
"limit": 10000,
"used": 1500,
"remaining": 8500,
"refill": {
"nextRefillAt": 1787003022920
}
}
},
{
"consumerId": "cons_X9Y8Z7",
"name": "Beta Inc",
"imageUrl": null,
"planId": null,
"createdAt": "2026-01-29T10:00:00Z",
"status": "active",
"apiKeyCount": 1,
"credits": null
}
]
}- total is the number of consumers in the project; filtered is the count after filters; totalPages = ceil(filtered / limit).
- credits shows the consumer’s pool (limit, used, remaining) and is null for unlimited consumers.
- credits.refill.nextRefillAt (epoch ms) is present when the consumer has a scheduled refill.
- Ordering ties break on consumerId, so pagination is stable across requests.
- A page past the end returns an empty consumers array (not an error).
/consumer/keysBearerList consumer keys
List a consumer’s keys with the shared credit balance.
consumerIdstringrequiredConsumer ID.
curl -X POST "https://api.reqkey.com/consumer/keys" \
-H "Authorization: Bearer reqkey_xxx..." \
-H "Content-Type: application/json" \
-d '{
"consumerId": "cons_A1B2C3D4"
}'{
"consumerId": "cons_A1B2C3D4",
"credits": {
"limit": 10000,
"remaining": 8500,
"used": 1500
},
"total": 2,
"keys": [
{
"keyId": "key_X1Y2Z3",
"key": "PaymentAPI_A1B2C3D4E5F6G7H8I9J0K1L2",
"status": "active",
"createdAt": "2026-01-30T12:34:56Z",
"allowedApis": [
"api_payment",
"api_analytics"
]
},
{
"keyId": "key_A9B8C7",
"key": "PaymentAPI_M1N2O3P4Q5R6S7T8U9V0W1X2",
"status": "active",
"createdAt": "2026-01-29T10:00:00Z",
"allowedApis": [
"*"
]
}
]
}- Credits are shown once at the consumer level — all keys share the same pool.
/consumer/deleteBearerDelete consumer
Soft (7-day recovery) or hard delete a consumer.
consumerIdstringrequiredConsumer ID to delete.
permanentbooleanfalse = soft delete (default), true = hard delete.
curl -X POST "https://api.reqkey.com/consumer/delete" \
-H "Authorization: Bearer reqkey_xxx..." \
-H "Content-Type: application/json" \
-d '{
"consumerId": "cons_A1B2C3D4",
"permanent": false
}'{
"consumerId": "cons_A1B2C3D4",
"deleted": true,
"permanent": false,
"deletedAt": "2026-01-30T12:34:56Z",
"keysAffected": 3,
"message": "Consumer soft deleted. Recoverable within 7 days."
}- Soft delete also soft-deletes every key under the consumer (recoverable 7 days).
- Hard delete removes the consumer, its keys, and its credit state permanently.