Complete documentation of all API endpoints and response codes.
Base URL
https://api.arkangelai.com/v1
Available Endpoints
Chat
| Method |
Endpoint |
Description |
| POST |
/chat |
Send a message and receive response |
| POST |
/chat/stream |
Send message with streaming response |
Conversations
| Method |
Endpoint |
Description |
| GET |
/conversations |
List conversations |
| GET |
/conversations/:id |
Get a conversation |
| PATCH |
/conversations/:id |
Update conversation |
| DELETE |
/conversations/:id |
Delete conversation |
| GET |
/conversations/search |
Search conversations |
| GET |
/conversations/:id/export |
Export conversation |
Files
| Method |
Endpoint |
Description |
| POST |
/files |
Upload a file |
| GET |
/files |
List files |
| GET |
/files/:id |
Get file information |
| DELETE |
/files/:id |
Delete file |
Usage
| Method |
Endpoint |
Description |
| GET |
/usage |
Get usage metrics |
| GET |
/usage/limits |
Check limits |
| GET |
/usage/endpoints |
Usage by endpoint |
| GET |
/usage/errors |
Error history |
| GET |
/usage/export |
Export usage data |
| POST |
/usage/alerts |
Configure alerts |
Rate Limits
All API endpoints enforce rate limits to ensure fair usage and platform stability. Limits are applied per user (identified by your API key) using a sliding window.
Default Limits
| Endpoint |
Limit |
Window |
POST /chat |
20 requests |
1 minute |
POST /chat/stream |
20 requests |
1 minute |
GET /conversations, GET /conversations/:id |
60 requests |
1 minute |
PATCH /conversations/:id, DELETE /conversations/:id |
30 requests |
1 minute |
POST /files |
30 requests |
1 minute |
GET /files, GET /files/:id, DELETE /files/:id |
60 requests |
1 minute |
GET /conversations/:id/export, GET /usage/export |
5 requests |
1 minute |
GET /usage, GET /usage/* |
60 requests |
1 minute |
Rate Limit Response
When you exceed a rate limit, the API returns a 429 Too Many Requests status with the following headers:
| Header |
Description |
X-RateLimit-Limit |
Maximum requests allowed in the current window |
X-RateLimit-Remaining |
Requests remaining in the current window |
X-RateLimit-Reset |
Unix timestamp when the window resets |
Retry-After |
Seconds to wait before retrying |
Wait for the duration specified in Retry-After before sending another request.
HTTP Status Codes
Successful Responses (2xx)
| Code |
Name |
Description |
| 200 |
OK |
Request successful |
| 201 |
Created |
Resource created successfully |
| 204 |
No Content |
Request successful with no response content |
Client Errors (4xx)
| Code |
Name |
Description |
| 400 |
Bad Request |
Malformed request or invalid parameters |
| 401 |
Unauthorized |
Missing or invalid API key |
| 403 |
Forbidden |
No permission to access resource |
| 404 |
Not Found |
Resource not found |
| 409 |
Conflict |
Conflict with current state |
| 422 |
Unprocessable Entity |
Valid data but not processable |
| 429 |
Too Many Requests |
Request limit exceeded |
Server Errors (5xx)
| Code |
Name |
Description |
| 500 |
Internal Server Error |
Internal server error |
| 502 |
Bad Gateway |
Gateway error |
| 503 |
Service Unavailable |
Service temporarily unavailable |
| 504 |
Gateway Timeout |
Request timeout |
Error Format
All error responses follow this format:
{
"error": {
"type": "invalid_request_error",
"code": "invalid_api_key",
"message": "The provided API key is invalid",
"param": "authorization",
"request_id": "req_abc123"
}
}
Error Fields
| Field |
Type |
Description |
type |
string |
Error category |
code |
string |
Specific error code |
message |
string |
Human-readable error description |
param |
string |
Parameter that caused the error (if applicable) |
request_id |
string |
Unique ID for tracking |
Error Types
| Type |
Description |
invalid_request_error |
Invalid or missing parameters |
authentication_error |
Authentication issues |
permission_error |
Missing required permissions |
not_found_error |
Resource doesn't exist |
rate_limit_error |
Request limit exceeded |
api_error |
Internal API error |
Common Error Codes
Authentication
| Code |
Description |
invalid_api_key |
Invalid API key |
missing_api_key |
No API key provided |
api_key_revoked |
API key revoked |
api_key_expired |
API key expired |
Requests
| Code |
Description |
invalid_message |
Empty or invalid message |
message_too_long |
Message exceeds character limit |
invalid_conversation_id |
Invalid conversation ID |
invalid_file_id |
Invalid file ID |
Files
| Code |
Description |
invalid_file_type |
Unsupported file type |
file_too_large |
File exceeds maximum size |
file_processing_failed |
Error processing file |
Limits
| Code |
Description |
rate_limit_exceeded |
Requests per second limit |
daily_limit_exceeded |
Daily limit reached |
monthly_limit_exceeded |
Monthly limit reached |
storage_limit_exceeded |
Storage limit reached |
Response Headers
| Header |
Description |
X-Request-Id |
Unique request ID |
X-RateLimit-Limit |
Requests per window limit |
X-RateLimit-Remaining |
Remaining requests |
X-RateLimit-Reset |
Limit reset timestamp |
Retry-After |
Seconds to wait (on 429) |
Error Handling Example
async function handleApiResponse(response) {
if (response.ok) {
return response.json();
}
const error = await response.json();
switch (response.status) {
case 401:
throw new Error('Authentication failed. Check your API key.');
case 429:
const retryAfter = response.headers.get('Retry-After');
throw new Error(`Limit exceeded. Try again in ${retryAfter} seconds.`);
case 500:
throw new Error('Server error. Try again later.');
default:
throw new Error(error.error?.message || 'Unknown error');
}
}
Next Steps