Documentation Index
Fetch the complete documentation index at: https://noorle.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Understand error responses, status codes, and rate limits in Noorle APIs.
REST API
{
"error": {
"code": "invalid_request",
"message": "Missing required parameter: api_key",
"details": {
"parameter": "api_key",
"reason": "required"
}
}
}
HTTP Status: 400 (varies by error type)
MCP/A2A (JSON-RPC 2.0)
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32602,
"message": "Invalid params",
"data": {
"expected": "string",
"actual": "number"
}
}
}
HTTP Status Codes
| Status | Meaning | Action |
|---|
| 200 | OK | Success |
| 201 | Created | Resource created successfully |
| 204 | No Content | Success, no body returned |
| 400 | Bad Request | Fix your request (validation error) |
| 401 | Unauthorized | Invalid or missing authentication |
| 403 | Forbidden | Authenticated but not authorized |
| 404 | Not Found | Resource doesn’t exist |
| 409 | Conflict | Request conflicts with existing state |
| 429 | Too Many Requests | Rate limit exceeded, retry later |
| 500 | Internal Server Error | Server error, not your fault |
| 502 | Bad Gateway | Upstream service error |
| 503 | Service Unavailable | Service temporarily down |
| 504 | Gateway Timeout | Request timed out |
Common Error Codes
Authentication Errors (401)
{
"error": {
"code": "unauthorized",
"message": "Invalid API key"
}
}
Causes:
- Missing
X-API-Key or Authorization header
- Invalid/expired token
- Revoked API key
Fix:
- Check API key format
- Refresh OAuth token
- Regenerate API key
Authorization Errors (403)
{
"error": {
"code": "forbidden",
"message": "This API key does not have permission to upload plugins"
}
}
Causes:
- API key lacks required scope
- User doesn’t have permission
- Resource access denied
Fix:
- Create API key with correct scopes
- Contact account administrator
- Check resource ownership
Validation Errors (400)
{
"error": {
"code": "validation_error",
"message": "Invalid request body",
"details": {
"field": "memory_limit",
"issue": "must be valid Kubernetes format (e.g., 512Mi)"
}
}
}
Causes:
- Missing required fields
- Invalid field types
- Constraint violations
Fix:
- Check required fields
- Validate field format
- Review API documentation
Resource Not Found (404)
{
"error": {
"code": "not_found",
"message": "Plugin 'my-plugin' not found"
}
}
Causes:
- Plugin/agent doesn’t exist
- Version not found
- Resource deleted
Fix:
- Verify resource ID/name
- Check in correct account
- List available resources
Rate Limit (429)
{
"error": {
"code": "rate_limit_exceeded",
"message": "Too many requests. Retry after 60 seconds"
}
}
Response headers:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1711123260
Fix:
- Wait until
X-RateLimit-Reset timestamp
- Implement exponential backoff
- Optimize batch requests
Server Error (500)
{
"error": {
"code": "internal_error",
"message": "An internal error occurred",
"request_id": "req_abc123xyz"
}
}
Causes:
- Server-side issue
- Database error
- External service failure
Fix:
- Retry with exponential backoff
- Report with
request_id
- Check status page
JSON-RPC Error Codes
Used by MCP and A2A protocols:
| Code | Message | Meaning |
|---|
| -32700 | Parse error | Invalid JSON |
| -32600 | Invalid Request | Bad method/params format |
| -32601 | Method not found | Method doesn’t exist |
| -32602 | Invalid params | Wrong parameter types |
| -32603 | Internal error | Server-side error |
Example:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32601,
"message": "Method not found: invalid_method"
}
}
Rate Limiting
Limits
Default rate limits (per account):
| Endpoint | Limit | Window |
|---|
| General API | 1,000 | 1 hour |
| Plugin upload | 100 | 1 hour |
| Tool calls | 10,000 | 1 hour |
| Agent creation | 50 | 1 day |
Every response includes:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1711123200
- Limit: Total requests allowed per window
- Remaining: Requests left in current window
- Reset: Unix timestamp when limit resets
Handling Rate Limits
1. Check Headers
if (response.headers['x-ratelimit-remaining'] === '0') {
const resetTime = response.headers['x-ratelimit-reset'];
console.log(`Rate limit reset at: ${new Date(resetTime * 1000)}`);
}
2. Exponential Backoff
import time
import random
def call_with_retry(func, max_retries=3):
for attempt in range(max_retries):
try:
return func()
except RateLimitError as e:
if attempt == max_retries - 1:
raise
wait_time = 2 ** attempt + random.random()
print(f"Rate limited. Waiting {wait_time}s...")
time.sleep(wait_time)
3. Batch Operations
# ❌ Slow: 100 individual requests
for plugin in plugins:
curl api/plugin/$plugin
# ✅ Better: Batch request
curl -X POST api/plugins/batch \
-d '{"ids": ["p1", "p2", ..., "p100"]}'
Error Handling Examples
Python
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
# Retry strategy
session = requests.Session()
retry = Retry(
total=5,
backoff_factor=1,
status_forcelist=[429, 500, 502, 503, 504]
)
adapter = HTTPAdapter(max_retries=retry)
session.mount('https://', adapter)
try:
resp = session.get(
'https://api.noorle.com/v1/capabilities',
headers={'X-API-Key': 'nk_...'},
timeout=10
)
resp.raise_for_status()
except requests.exceptions.HTTPError as e:
if e.response.status_code == 429:
reset_time = e.response.headers['X-RateLimit-Reset']
print(f"Rate limited until {reset_time}")
else:
print(f"Error: {e.response.json()}")
except requests.exceptions.RequestException as e:
print(f"Connection error: {e}")
JavaScript
async function apiCall(url: string, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
const response = await fetch(url, {
headers: { "X-API-Key": "nk_..." },
});
if (!response.ok) {
if (response.status === 429) {
const resetTime = response.headers.get("X-RateLimit-Reset");
const waitTime = Math.max(
1000,
Number(resetTime) * 1000 - Date.now()
);
console.log(`Rate limited. Waiting ${waitTime}ms`);
await new Promise((resolve) => setTimeout(resolve, waitTime));
continue;
}
throw new Error(`HTTP ${response.status}`);
}
return response.json();
} catch (error) {
if (i === retries - 1) throw error;
const backoff = Math.pow(2, i) * 1000;
await new Promise((resolve) => setTimeout(resolve, backoff));
}
}
}
cURL with Retry
#!/bin/bash
function api_call() {
local url=$1
local max_retries=3
local retry=0
while [ $retry -lt $max_retries ]; do
response=$(curl -s -w "\n%{http_code}" \
-H "X-API-Key: nk_..." \
"$url")
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | head -n-1)
if [ "$http_code" == "200" ]; then
echo "$body"
return 0
elif [ "$http_code" == "429" ]; then
reset_time=$(curl -s -I -H "X-API-Key: nk_..." "$url" | \
grep "X-RateLimit-Reset" | awk '{print $2}')
sleep $((reset_time - $(date +%s)))
((retry++))
else
echo "Error: $body"
return 1
fi
done
return 1
}
Debugging
Request ID
Every response includes a unique request ID for debugging:
curl -v https://api.noorle.com/v1/capabilities \
-H "X-API-Key: nk_..."
# Response headers:
# X-Request-ID: req_abc123xyz
Report this ID when contacting support.
Verbose Logging
Enable debug logging:
# cURL
curl -v https://api.noorle.com/v1/capabilities
# Python
import logging
logging.basicConfig(level=logging.DEBUG)
# Node.js
process.env.DEBUG = 'noorle:*'
Health Check
Check API status:
curl https://api.noorle.com/health
# Response:
# {
# "status": "healthy",
# "version": "v1",
# "timestamp": "2024-03-22T10:30:45Z"
# }
Status Page
Real-time status: https://status.noorle.com
- Current incidents
- Maintenance windows
- Historical uptime
- API performance metrics
Next Steps