Skip to main content

API Key Authentication

API Keys are used by Agents (developers) to authenticate API requests.

Overview

ZhenRent uses Bearer token authentication with API keys for all agent-side requests.

Authorization: Bearer zr_live_your_api_key_here

API Key Format: zr_{environment}_{random_string}

  • zr_live_* - Production keys
  • zr_test_* - Test environment keys (coming soon)

Creating an API Key

Step 1: Access Dashboard

  1. Log in to ZhenRent Dashboard
  2. Navigate to API Keys section
  3. Click Create New Key

Step 2: Configure Key

Key Configuration:

SettingDescriptionRecommendation
Key NameDescriptive identifierUse environment name (e.g., "Production", "Development")
PermissionsAPI access scopeGrant minimum required permissions
IP WhitelistAllowed IP addresses (optional)Use for production keys
ExpirationAuto-expiration date (optional)Set for temporary keys

Available Permissions:

  • task:create - Create new tasks
  • task:read - Query tasks and results
  • task:cancel - Cancel pending tasks
  • webhook - Receive webhook notifications

Example Configuration:

Name: Production API
Permissions: task:create, task:read
IP Whitelist: 203.0.113.0/24
Expiration: None

Step 3: Save Key Securely

After creation, your API key is displayed once. Copy and store it securely.

Your API Key:
zr_live_l2HqGwGQVq0pUKshFM2AZiHfFX6LK

Warning: This key provides full access to your account. Store it like a password.

Using API Keys

In HTTP Requests

Include the API key in the Authorization header:

curl "https://www.zhenrent.com/api/v1/tasks" \
-H "Authorization: Bearer zr_live_your_api_key"

In Python

import os
import requests

API_KEY = os.getenv("ZHENRENT_API_KEY")
BASE_URL = "https://www.zhenrent.com/api/v1"

headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}

response = requests.get(f"{BASE_URL}/tasks", headers=headers)

In JavaScript/Node.js

const API_KEY = process.env.ZHENRENT_API_KEY;
const BASE_URL = 'https://www.zhenrent.com/api/v1';

const response = await fetch(`${BASE_URL}/tasks`, {
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
}
});

In Go

package main

import (
"net/http"
"os"
)

func main() {
apiKey := os.Getenv("ZHENRENT_API_KEY")

req, _ := http.NewRequest("GET", "https://www.zhenrent.com/api/v1/tasks", nil)
req.Header.Set("Authorization", "Bearer "+apiKey)

client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
}

Security Best Practices

1. Use Environment Variables

Never hardcode API keys in your source code.

Bad (Insecure):

API_KEY = "zr_live_l2HqGwGQVq0pUKshFM2AZiHfFX6LK"  # Never do this!

Good (Secure):

import os
API_KEY = os.getenv("ZHENRENT_API_KEY")

Set environment variable:

# Linux/Mac
export ZHENRENT_API_KEY="zr_live_your_key"

# Windows
set ZHENRENT_API_KEY=zr_live_your_key

2. Use .env Files (Local Development)

# .env
ZHENRENT_API_KEY=zr_live_your_key_here

Python (.env loading):

from dotenv import load_dotenv
load_dotenv()

API_KEY = os.getenv("ZHENRENT_API_KEY")

JavaScript (.env loading):

require('dotenv').config();

const API_KEY = process.env.ZHENRENT_API_KEY;

3. Add .env to .gitignore

Prevent accidental commits:

# .gitignore
.env
.env.local
.env.production
*.pem

4. Rotate Keys Regularly

Recommended schedule:

  • Production keys: Every 90 days
  • Development keys: Every 180 days
  • After team member departure: Immediately

Rotation process:

  1. Create new API key
  2. Update application configuration
  3. Test with new key
  4. Delete old key

5. Use Different Keys per Environment

EnvironmentKey PrefixPurpose
Developmentzr_test_*Local testing
Stagingzr_live_*Pre-production testing
Productionzr_live_*Live traffic

Never use production keys in development.

6. Implement IP Whitelisting

For production keys, restrict access to known IP addresses:

Dashboard → API Keys → Edit → IP Whitelist
203.0.113.0/24

Benefits:

  • Prevents unauthorized access even if key is leaked
  • Reduces attack surface
  • Compliance requirement for some industries

7. Monitor API Key Usage

Check usage statistics regularly:

Dashboard → API Keys → Usage Statistics

Warning signs:

  • Unexpected traffic spikes
  • Requests from unknown IPs
  • Unusual error rates
  • Off-hours activity

8. Implement Key Validation

Verify API key format before making requests:

import re

def validate_api_key(key):
"""Validate ZhenRent API key format"""
pattern = r'^zr_(live|test)_[A-Za-z0-9\-_]{32}$'
if not re.match(pattern, key):
raise ValueError("Invalid API key format")
return True

# Usage
try:
validate_api_key(API_KEY)
except ValueError as e:
print(f"Error: {e}")
exit(1)

Managing Multiple Keys

Use Case: Multiple Applications

Create separate keys for each application:

Key 1: E-commerce Platform (task:create, task:read)
Key 2: Analytics Dashboard (task:read only)
Key 3: Mobile Backend (task:create, task:read, webhook)

Benefits:

  • Granular permission control
  • Easy to revoke specific app access
  • Better audit trail

Key Naming Convention

Use descriptive names:

Format: {App}-{Environment}-{Purpose}

Examples:
- MainApp-Production-API
- Analytics-Staging-ReadOnly
- MobileBackend-Dev-Testing

Troubleshooting

Error: 401 Unauthorized

Cause: Invalid or missing API key

Solutions:

  1. Check key format

    # Correct
    headers = {"Authorization": "Bearer zr_live_abc123"}

    # Wrong (missing "Bearer")
    headers = {"Authorization": "zr_live_abc123"}
  2. Verify key is active

    Dashboard → API Keys → Status
  3. Check for typos

    # Print key (first 10 chars only for security)
    print(f"Using key: {API_KEY[:10]}...")
  4. Ensure key hasn't expired

    Dashboard → API Keys → Expiration Date

Error: 403 Forbidden

Cause: Insufficient permissions

Solution: Add required permission to API key

Dashboard → API Keys → Edit → Permissions → Add "task:create"

Error: 429 Rate Limit Exceeded

Cause: Too many requests

Solution: Implement exponential backoff

import time

def api_request_with_retry(url, max_retries=3):
for attempt in range(max_retries):
response = requests.get(url, headers=headers)

if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
print(f"Rate limited. Retrying after {retry_after}s...")
time.sleep(retry_after)
continue

return response

raise Exception("Max retries exceeded")

API Key Lifecycle

Creation

User creates key → Platform generates random string → Key saved (hashed)

Storage

Platform: SHA-256 hash stored in database
Client: Plain text stored in environment variable

Validation

Client sends key → Platform hashes → Compares with stored hash → Grants/Denies access

Revocation

User deletes key → Hash removed from database → All requests with that key fail

Rate Limits

API keys have usage limits to prevent abuse:

TierRequests/MinuteRequests/Day
Free10010,000
Paid1,000100,000
EnterpriseCustomCustom

Rate limit headers (included in every response):

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1680261600

Next Steps