page_shot / API_GUIDE.md
CatPtain's picture
Upload 2 files
2018c79 verified
# API Authentication & Usage Guide
## πŸ” Setting Up API Key in Hugging Face Spaces
### Step 1: Generate Secure API Key
```bash
# Generate random API key (example methods)
node -e "console.log('sk-' + require('crypto').randomBytes(32).toString('hex'))"
# Or use Python
python -c "import secrets; print('sk-' + secrets.token_hex(32))"
```
### Step 2: Configure in HF Spaces
1. Navigate to your Space: `https://huggingface.co/spaces/your-username/space-name`
2. Click **"Settings"** tab
3. Click **"Variables"** section
4. Add this environment variable:
| Variable | Value | Description |
|----------|-------|-------------|
| `API_KEY` | `sk-your-secure-key-here` | Single API key for authentication |
### Step 3: Test Authentication
```bash
# Test without API key (should fail if authentication enabled)
curl -X POST https://your-space.hf.space/screenshot \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'
# Test with API key (should work)
curl -X POST https://your-space.hf.space/screenshot \
-H "Authorization: Bearer your-api-key-here" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'
```
## πŸ“Š Understanding Server Status Responses
### Normal Operation
```json
{
"status": "running",
"system": { "cpuUsage": "25%" },
"queue": { "activeRequests": 1, "queuedRequests": 0 }
}
```
### Server Busy (CPU > 95%)
```json
{
"status": "busy",
"error": "Server is currently overloaded",
"cpuUsage": "96%",
"queueLength": 3
}
```
### Queue Full Response
```json
{
"status": "busy",
"error": "Request queue timeout",
"queueLength": 10
}
```
## πŸ”„ Implementing Retry Logic
### JavaScript Retry Pattern
```javascript
async function screenshotWithRetry(url, options = {}, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await fetch('/screenshot', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer your-api-key'
},
body: JSON.stringify({ url, ...options })
});
if (response.ok) {
return await response.blob();
}
if (response.status === 503) {
const error = await response.json();
if (error.status === 'busy') {
console.log(`Attempt ${attempt}: Server busy, retrying...`);
await new Promise(resolve => setTimeout(resolve, 2000 * attempt));
continue;
}
}
// Other errors, don't retry
throw new Error(`API Error: ${response.status}`);
} catch (error) {
if (attempt === maxRetries) throw error;
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
}
}
}
```
### Python Retry Pattern
```python
import time
import requests
from typing import Optional
def screenshot_with_retry(url: str, api_key: str, max_retries: int = 3) -> Optional[bytes]:
for attempt in range(1, max_retries + 1):
try:
response = requests.post(
'https://your-space.hf.space/screenshot',
headers={'Authorization': f'Bearer {api_key}', 'Content-Type': 'application/json'},
json={'url': url},
timeout=30
)
if response.status_code == 200:
return response.content
if response.status_code == 503:
error_data = response.json()
if error_data.get('status') == 'busy':
print(f"Attempt {attempt}: Server busy (CPU: {error_data.get('cpuUsage', 'N/A')})")
time.sleep(2 * attempt)
continue
response.raise_for_status()
except requests.RequestException as e:
if attempt == max_retries:
raise e
time.sleep(attempt)
return None
```
## 🚨 Rate Limiting & Best Practices
### Rate Limit Headers
The API returns rate limiting information:
```
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1640995200
```
### Best Practices
1. **Implement exponential backoff** for retries
2. **Cache results** when possible
3. **Use appropriate image quality** (70-80% usually sufficient)
4. **Monitor your usage** via `/status` endpoint
5. **Handle queue timeouts** gracefully
### Production Usage Example
```javascript
class ScreenshotAPI {
constructor(apiKey, baseUrl) {
this.apiKey = apiKey;
this.baseUrl = baseUrl;
this.requestCount = 0;
this.resetTime = 0;
}
async screenshot(url, options = {}) {
// Check rate limit
if (this.requestCount >= 95 && Date.now() < this.resetTime) {
throw new Error('Rate limit approached, waiting...');
}
const response = await this.makeRequest('/screenshot', {
method: 'POST',
body: JSON.stringify({ url, ...options })
});
// Update rate limit tracking
this.requestCount = parseInt(response.headers.get('X-RateLimit-Remaining') || '0');
this.resetTime = parseInt(response.headers.get('X-RateLimit-Reset') || '0') * 1000;
return response;
}
async makeRequest(endpoint, options = {}) {
return fetch(this.baseUrl + endpoint, {
...options,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.apiKey}`,
...options.headers
}
});
}
}
```
## πŸ”§ Troubleshooting
### Common Issues
| Error | Cause | Solution |
|-------|-------|----------|
| `401 Unauthorized` | Missing API key | Add `Authorization: Bearer` header |
| `403 Forbidden` | Invalid API key | Check key spelling/validity |
| `503 Service Unavailable` | Server overloaded | Implement retry with delay |
| `429 Too Many Requests` | Rate limit exceeded | Wait for reset time |
### Performance Optimization
- Use smaller dimensions for faster processing
- Lower quality settings for non-critical uses
- Batch requests with appropriate delays
- Monitor CPU usage via `/status`