Error Handling
The Flow API uses standard HTTP status codes and provides detailed error information to help you debug issues.
Error Response Format
All errors follow a consistent format:
{
"error": {
"type": "error_type",
"message": "Human-readable error message",
"code": "ERROR_CODE",
"details": [
{
"field": "field_name",
"message": "Field-specific error message"
}
],
"request_id": "req_abc123..."
}
}
Error Types
authentication_error (401)
Invalid or missing API key.
{
"error": {
"type": "authentication_error",
"message": "Invalid API key",
"code": "INVALID_API_KEY"
}
}
Solutions:
- Check that your API key is correct
- Ensure the
Authorizationheader is formatted correctly:Bearer flow_sk_live_... - Verify the API key hasn't been revoked
authorization_error (403)
Insufficient permissions.
{
"error": {
"type": "authorization_error",
"message": "Insufficient permissions",
"code": "INSUFFICIENT_PERMISSIONS",
"details": [
{
"field": "permission",
"message": "Required permission: posts:write"
}
]
}
}
Solutions:
- Check your API key permissions
- Create a new API key with the required permissions
validation_error (400)
Invalid request data.
{
"error": {
"type": "validation_error",
"message": "Invalid request",
"code": "VALIDATION_ERROR",
"details": [
{
"field": "channelId",
"message": "Channel ID is required"
},
{
"field": "content",
"message": "Content must be at least 1 character"
}
]
}
}
Solutions:
- Review the error details for specific field issues
- Check the API documentation for required fields and formats
- Validate your request payload before sending
not_found (404)
Resource not found.
{
"error": {
"type": "not_found",
"message": "Post not found",
"code": "POST_NOT_FOUND"
}
}
Solutions:
- Verify the resource ID is correct
- Check that the resource belongs to your account
- Ensure the resource hasn't been deleted
rate_limit_error (429)
Rate limit exceeded.
{
"error": {
"type": "rate_limit_error",
"message": "Rate limit exceeded",
"code": "RATE_LIMIT_EXCEEDED",
"retry_after": 45
}
}
Solutions:
- Wait for the
retry_afterseconds before retrying - Implement exponential backoff
- Consider using batch endpoints for multiple operations
- Check rate limit headers:
X-RateLimit-Remaining,X-RateLimit-Reset
server_error (500)
Internal server error.
{
"error": {
"type": "server_error",
"message": "Internal server error",
"code": "INTERNAL_ERROR",
"request_id": "req_abc123..."
}
}
Solutions:
- Retry the request after a short delay
- If the error persists, contact support with the
request_id - Check status.flow.dev for service status
HTTP Status Codes
| Code | Meaning | Description |
|---|---|---|
| 200 | OK | Request succeeded |
| 201 | Created | Resource created successfully |
| 400 | Bad Request | Invalid request data |
| 401 | Unauthorized | Invalid or missing API key |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource not found |
| 409 | Conflict | Resource conflict (e.g., duplicate) |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server error |
| 503 | Service Unavailable | Service temporarily unavailable |
Error Handling Best Practices
1. Always Check Status Codes
const response = await fetch('https://api.flow.dev/v1/posts', {
headers: {
'Authorization': `Bearer ${apiKey}`,
},
});
if (!response.ok) {
const error = await response.json();
// Handle error
}
2. Use SDKs for Better Error Handling
SDKs provide typed error classes:
import { Flow, FlowError } from '@flowdev/sdk';
try {
const post = await flow.posts.create({
channelId: 'invalid',
content: 'Test',
});
} catch (error) {
if (error instanceof FlowError) {
switch (error.status) {
case 401:
console.error('Authentication failed');
break;
case 403:
console.error('Permission denied');
break;
case 404:
console.error('Resource not found');
break;
case 429:
console.error(`Rate limited. Retry after ${error.retryAfter}s`);
break;
default:
console.error('API error:', error.message);
}
}
}
3. Implement Retry Logic
For transient errors (429, 500, 503):
async function retryRequest<T>(
fn: () => Promise<T>,
maxRetries = 3
): Promise<T> {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (error instanceof FlowError) {
// Don't retry client errors
if (error.status >= 400 && error.status < 500) {
throw error;
}
// Retry server errors with exponential backoff
if (error.status >= 500 || error.status === 429) {
const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
}
throw error;
}
}
throw new Error('Max retries exceeded');
}
4. Log Request IDs
Always log request_id for debugging:
catch (error) {
if (error instanceof FlowError && error.requestId) {
console.error(`Request ID: ${error.requestId}`, error);
// Include request_id when contacting support
}
}
5. Handle Validation Errors Gracefully
catch (error) {
if (error instanceof FlowError && error.status === 400) {
if (error.details) {
error.details.forEach(detail => {
console.error(`${detail.field}: ${detail.message}`);
});
}
}
}
Common Error Scenarios
Invalid API Key
curl https://api.flow.dev/v1/posts \
-H "Authorization: Bearer invalid_key"
Response:
{
"error": {
"type": "authentication_error",
"message": "Invalid API key",
"code": "INVALID_API_KEY"
}
}
Missing Required Field
curl -X POST https://api.flow.dev/v1/posts \
-H "Authorization: Bearer flow_sk_live_..." \
-H "Content-Type: application/json" \
-d '{}'
Response:
{
"error": {
"type": "validation_error",
"message": "Invalid request",
"code": "VALIDATION_ERROR",
"details": [
{
"field": "channelId",
"message": "Channel ID is required"
}
]
}
}
Rate Limit Exceeded
# After making too many requests
curl https://api.flow.dev/v1/posts \
-H "Authorization: Bearer flow_sk_live_..."
Response:
{
"error": {
"type": "rate_limit_error",
"message": "Rate limit exceeded",
"code": "RATE_LIMIT_EXCEEDED",
"retry_after": 45
}
}
Headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1703123456
Getting Help
If you encounter an error you can't resolve:
- Check the error
codeandmessage - Review the
detailsarray for field-specific issues - Include the
request_idwhen contacting support - Check status.flow.dev for service issues
- Contact support: support@flow.dev