Skip to main content

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 Authorization header 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_after seconds 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

CodeMeaningDescription
200OKRequest succeeded
201CreatedResource created successfully
400Bad RequestInvalid request data
401UnauthorizedInvalid or missing API key
403ForbiddenInsufficient permissions
404Not FoundResource not found
409ConflictResource conflict (e.g., duplicate)
429Too Many RequestsRate limit exceeded
500Internal Server ErrorServer error
503Service UnavailableService 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:

  1. Check the error code and message
  2. Review the details array for field-specific issues
  3. Include the request_id when contacting support
  4. Check status.flow.dev for service issues
  5. Contact support: support@flow.dev