Skip to content

API Key Reference

Complete reference for API key format, permissions, rate limits, and technical specifications.


All API keys use a consistent format for easy identification:

idx_{role_prefix}{random_string}
Component Description Example
Prefix Always idx_ idx_
Role Indicator Optional single character a (admin), b (broker), g (agent)
Random String Cryptographically secure random characters a1b2c3d4e5f6g7h8i9j0
idx_live_SAgFqBpAMP_znpf3GffgCI (Admin key)
idx_broker_Kp9mNq2rSt3vWx4yZ5 (Broker key)
idx_agent_Ab7cDe8fGh9iJk0lMn1 (Agent key)

Full Access
Permission Category Capabilities
Properties Read, create, update, delete all properties
Users Create, update, deactivate all users (admins, brokers, agents)
Brokerages Create, update, delete all brokerages
API Keys Create, view, revoke all API keys
System Config Modify platform settings, feature flags
Data Management Export, import, clear database tables
Analytics Access all usage metrics and reports
Brokerage Access
Permission Category Capabilities
Properties Read all properties, update listings for assigned brokerage
Agents Create, update, deactivate agents within assigned brokerage
Leads View and manage leads for assigned brokerage
Brokerage Settings Update settings for assigned brokerage only
Reports Access brokerage-specific analytics
API Keys Create and revoke keys for own brokerage (agent-level only)
Personal Access
Permission Category Capabilities
Properties Read-only access to all properties
Own Profile Update own agent profile and preferences
Leads View leads assigned to self only
Tours Create and manage tour requests
Suggestions Submit property update suggestions
Favorites Manage own saved properties

These are the limits the server actually enforces today, and they work differently from the per-key table below.

/api/listings, /api/search, /api/suggestions and /api/embed are public: the tenant sites call them from the browser, so no credential can gate them. What a key buys on these paths is not access, it is identity.

Caller Bucket Default ceiling
No key Per client IP 120 requests / 60s
Valid idx_ key Per key 600 requests / 60s
Revoked or expired idx_ key None 403

Send the key as Authorization: Bearer idx_.... A server-side integration that does so becomes countable and throttleable on its own, and can be switched off by revoking the key without changing anything for the public.

Two things to know before depending on the numbers:

  • The window is in-process, per worker. The real ceiling is the number above multiplied by the worker count, and a restart forgets every window. It is a speed bump for scrapers, not a quota system.
  • Internal callers are exempt. Our own server-side rendering reaches the API from inside the Docker network; limiting private addresses would throttle the site while leaving a direct-to-API scraper untouched.

Both ceilings are environment variables: RATE_LIMIT_REQUESTS, RATE_LIMIT_KEYED_REQUESTS and RATE_LIMIT_WINDOW_SECONDS.

The tables below describe the intended shape of per-key limiting for authenticated admin endpoints. They are not all enforced yet; where they differ from the section above, the section above is what runs.

Default limits per API key (adjustable by administrators):

Time Window Limit Applies To
Per Minute 100 requests All roles
Per Hour 1,000 requests All roles
Per Day 10,000 requests All roles
Endpoint Category Per Minute Per Hour
Read Operations (GET) 100 1,000
Write Operations (POST, PUT, PATCH) 50 500
Delete Operations (DELETE) 10 100
Search/Analytics 30 300

Every API response includes rate limit information:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1640995200
Header Type Description
X-RateLimit-Limit Integer Maximum requests allowed in current window
X-RateLimit-Remaining Integer Requests remaining in current window
X-RateLimit-Reset Unix Timestamp When the rate limit window resets
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1640995260
{
"error": "rate_limit_exceeded",
"message": "Rate limit exceeded. Retry after 60 seconds.",
"retry_after": 60
}

sequenceDiagram
    Client->>API: Request with X-API-Key header
    API->>Database: Validate key
    Database-->>API: Key valid + role
    API->>API: Check permissions
    API-->>Client: Response or 401/403
Response Code Meaning Action Required
200-299 Authenticated and authorized Continue using key
401 Unauthorized Invalid or revoked key Generate new key
403 Forbidden Valid key, insufficient permissions Request higher-privilege key
429 Too Many Requests Rate limit exceeded Implement backoff, reduce request rate

Each API key stores the following metadata:

Field Type Description
id UUID Unique key identifier
key String Hashed API key value (original never stored)
name String User-provided descriptive name
role Enum admin, broker, or agent
brokerage_id UUID Associated brokerage (null for admin keys)
created_at DateTime Timestamp of creation
created_by UUID User who created the key
last_used_at DateTime Most recent successful authentication
revoked_at DateTime Timestamp when revoked (null if active)
revoked_by UUID User who revoked the key

Metric Description Retention Period
Request Count Total successful requests 90 days
Error Count Failed requests (4xx, 5xx) 90 days
Response Time Average latency per endpoint 30 days
Data Transfer Bytes sent/received 30 days
Endpoint Usage Requests per endpoint path 90 days
{
"timestamp": "2024-12-28T10:30:00Z",
"api_key_id": "550e8400-e29b-41d4-a716-446655440000",
"endpoint": "/api/v1/properties",
"method": "GET",
"status_code": 200,
"response_time_ms": 45,
"bytes_sent": 15234,
"bytes_received": 256,
"ip_address": "203.0.113.42",
"user_agent": "Custom Integration v1.2.3"
}

  • Algorithm: Cryptographically secure pseudo-random number generator (CSPRNG)
  • Entropy: 256 bits minimum
  • Character Set: Base62 (A-Z, a-z, 0-9)
  • Length: 32-48 characters (excluding prefix)
  • Hashing Algorithm: bcrypt with work factor 12
  • Original Key: Never stored, only hash
  • Salt: Unique per key, generated by bcrypt

Keys are validated in constant time to prevent timing attacks.