Tiers & Limits
Choose the tier that fits your usage.
Table of contents
Feature matrix
| Feature | FREE | STARTER | DEVELOPER | BUSINESS |
|---|---|---|---|---|
| Max characters | 3 | 5 | 30 | 100 |
| AI ops / month | 0 | Unlimited (BYOK) | Unlimited (BYOK) | Unlimited (BYOK) |
| Min sync interval | 60s | 30s | 15s | 5s |
| Max API keys | 1 | 1 | 3 | 10 |
| Max members | 1 | 1 | 3 | 10 |
| File sync | ✅ | ✅ | ✅ | ✅ |
| AI extraction | ❌ | ✅ | ✅ | ✅ |
| Direct memory write | ❌ | ✅ | ✅ | ✅ |
| Import pipeline | ❌ | ❌ | ✅ | ✅ |
| Auto-capture / Auto-recall | ❌ | ✅ | ✅ | ✅ |
| Team sharing | ❌ | ❌ | ✅ | ✅ |
| Smart retrieval | ❌ | ❌ | ✅ | ✅ |
| Webhooks & audit trail | ❌ | ❌ | ❌ | ✅ |
BYOK is mandatory for all paid tiers. You provide your own AI provider key and are billed directly by your provider. HippoDid charges for infrastructure only. Infrastructure rate limits (see below) still apply.
Rate limit buckets
HippoDid uses per-operation buckets for fine-grained rate limiting. Each bucket has its own limit — a burst of search requests won’t affect your write quota.
Rates (requests per minute, sustained)
| Bucket | What it covers | FREE | STARTER | DEVELOPER | BUSINESS |
|---|---|---|---|---|---|
SEARCH | GET /characters, /memories, /memories/search | 10 | 30 | 60 | 200 |
WRITE | POST /characters (create), PUT /memories | 10 | 30 | 60 | 200 |
SYNC | Paths containing /sync or /v1/files/ | 2 | 4 | 8 | 20 |
MANAGEMENT | DELETE, GET /tier, PUT profile/aliases | 5 | 30 | 120 | 600 |
AI_PROXY | Reserved for future AI proxy endpoints | 0 | 30 | 60 | 200 |
Burst allowance
For the first 10 seconds of a rate limit window, the effective limit is 2× the sustained rate. This accommodates startup bursts (e.g., loading all character data on app boot) without eating into your sustained quota.
Request → bucket mapping
| Request | Bucket |
|---|---|
GET /v1/characters/** | SEARCH |
POST /v1/characters/{id}/memories/search | SEARCH |
POST /v1/characters (create) | WRITE |
PUT /v1/characters/{id}/memories/{id} | WRITE |
Anything with /sync in the path | SYNC |
Anything under /v1/files/ | SYNC |
POST /v1/characters/{id}/import | SYNC |
| DELETE requests | MANAGEMENT |
GET /v1/tier | MANAGEMENT |
PUT /v1/characters/{id}/profile | MANAGEMENT |
PUT /v1/characters/{id}/aliases | MANAGEMENT |
Rate limit headers
Every response includes:
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 27
X-RateLimit-Reset: 1705312260
X-RateLimit-Bucket: WRITE
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests for this bucket in the current 1-minute window |
X-RateLimit-Remaining | Requests remaining before the limit is hit |
X-RateLimit-Reset | Unix timestamp (seconds) when the window resets |
X-RateLimit-Bucket | Which bucket this request was counted against |
429 Too Many Requests
When you exceed a rate limit:
{
"error": {
"type": "TierLimitExceeded",
"message": "Rate limit exceeded for bucket WRITE on tier STARTER",
"status": 429
}
}
Use the X-RateLimit-Reset header to determine when to retry:
import time
response = requests.post(url, headers=headers, json=body)
if response.status_code == 429:
reset_at = int(response.headers.get("X-RateLimit-Reset", 0))
wait_secs = max(0, reset_at - int(time.time())) + 1
time.sleep(wait_secs)
# retry
Character limit (429)
Attempting to create a character beyond your tier’s maxCharacters returns:
{
"error": {
"type": "CharacterLimitExceeded",
"message": "Character limit reached for tier STARTER (max: 5)",
"status": 429
}
}
Archive unused characters to free up slots, or upgrade your tier.
Upgrade path
FREE → STARTER → DEVELOPER → BUSINESS
Upgrades take effect immediately. Downgrades take effect at the end of the billing period. Existing characters and memories are preserved on downgrade — you’ll just be unable to create new ones beyond the lower tier’s limit until you’re within bounds.
Contact support@hippodid.com for Enterprise pricing (custom limits, SLA, dedicated support).