Error Response Format

All errors follow RFC 7807 (Problem Details for HTTP APIs) and return a consistent JSON structure:
{
  "error": {
    "type": "error_type_identifier",
    "title": "Human-Readable Title",
    "status": 400,
    "detail": "Detailed error message explaining what went wrong",
    "request_id": "req_abc123xyz",
    "timestamp": "2025-11-03T10:30:00Z",
    "metadata": {
      "additional": "context-specific data"
    },
    "links": {
      "docs": "https://docs.getbluma.com/errors#error_type",
      "support": "https://getbluma.com/support"
    }
  }
}

HTTP Status Codes

Status CodeMeaningCommon Causes
200SuccessRequest completed successfully
201CreatedResource created successfully
202AcceptedAsync operation queued
400Bad RequestInvalid request data
401UnauthorizedMissing or invalid API key
402Payment RequiredInsufficient credits
403ForbiddenAPI key lacks permission
404Not FoundResource doesn’t exist
429Too Many RequestsRate limit exceeded
500Internal Server ErrorServer-side error
503Service UnavailableTemporary outage

Common Errors

Authentication Errors

{
  "error": {
    "type": "authentication_error",
    "title": "Authentication Required",
    "status": 401,
    "detail": "Valid API key required. Include it in the Authorization header as 'Bearer YOUR_API_KEY'.",
    "links": {
      "docs": "https://docs.getbluma.com/authentication"
    }
  }
}
Solution: Include your API key in the Authorization header:
-H "Authorization: Bearer bluma_live_your_api_key"
{
  "error": {
    "type": "authentication_error",
    "title": "Invalid API Key",
    "status": 401,
    "detail": "The API key provided is invalid or has been revoked.",
    "metadata": {
      "key_prefix": "bluma_live_abc123"
    },
    "links": {
      "docs": "https://docs.getbluma.com/authentication",
      "manage_keys": "https://getbluma.com/brand/api-keys"
    }
  }
}
Solution: Verify your API key is correct. Check for typos, extra spaces, or expired/revoked keys.
{
  "error": {
    "type": "permission_denied",
    "title": "Insufficient Permissions",
    "status": 403,
    "detail": "This API key does not have the required scope to perform this action.",
    "metadata": {
      "required_scope": "videos:create",
      "available_scopes": ["videos:read", "templates:list"]
    }
  }
}
Solution: Create a new API key with the required scopes or use a different key.

Credit & Payment Errors

{
  "error": {
    "type": "insufficient_credits",
    "title": "Insufficient Credits",
    "status": 402,
    "detail": "You have 2 credits, but 3 are required for this video generation.",
    "metadata": {
      "credits_required": 3,
      "credits_available": 2,
      "credit_cost_breakdown": {
        "base": 1,
        "resolution_multiplier": 1.5,
        "duration_multiplier": 2
      }
    },
    "links": {
      "docs": "https://docs.getbluma.com/concepts/credits",
      "upgrade": "https://getbluma.com/billing"
    }
  }
}
Solution:
  • Purchase more credits or upgrade your plan
  • Use a template with lower credit requirements
  • Reduce video resolution or duration

Validation Errors

{
  "error": {
    "type": "invalid_request",
    "title": "Validation Error",
    "status": 400,
    "detail": "Request body contains validation errors.",
    "validation_errors": [
      {
        "field": "template_id",
        "message": "Required field is missing"
      },
      {
        "field": "context.prompt",
        "message": "String must contain at least 10 characters"
      }
    ]
  }
}
Solution: Review the validation_errors array and fix each field mentioned.
{
  "error": {
    "type": "not_found",
    "title": "Resource Not Found",
    "status": 404,
    "detail": "Video with ID 'batch_xyz789' not found.",
    "metadata": {
      "resource_type": "video",
      "resource_id": "batch_xyz789"
    }
  }
}
Solution:
  • Verify the resource ID is correct
  • Check that the resource belongs to your account
  • Ensure the resource hasn’t been deleted

Rate Limit Errors

{
  "error": {
    "type": "rate_limit_exceeded",
    "title": "Rate Limit Exceeded",
    "status": 429,
    "detail": "You have exceeded the rate limit of 1,000 requests per hour.",
    "metadata": {
      "limit": 1000,
      "retry_after": 3600,
      "current_usage": 1000
    },
    "links": {
      "docs": "https://docs.getbluma.com/concepts/rate-limits",
      "upgrade": "https://getbluma.com/billing"
    }
  }
}
Headers Returned:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1699127600
Retry-After: 3600
Solution:
  • Wait until the rate limit resets (check Retry-After header)
  • Implement exponential backoff
  • Upgrade to a higher tier for increased limits

Server Errors

{
  "error": {
    "type": "internal_error",
    "title": "Internal Server Error",
    "status": 500,
    "detail": "An unexpected error occurred. Our team has been notified.",
    "request_id": "req_abc123xyz",
    "timestamp": "2025-11-03T10:30:00Z",
    "links": {
      "support": "mailto:stephen@getbluma.com"
    }
  }
}
Solution:
  • Retry the request after a brief delay
  • Contact stephen@getbluma.com with the request_id for investigation
{
  "error": {
    "type": "service_unavailable",
    "title": "Service Temporarily Unavailable",
    "status": 503,
    "detail": "The service is temporarily unavailable due to maintenance.",
    "metadata": {
      "retry_after": 300
    }
  }
}
Solution:
  • Wait and retry after the time specified in retry_after (seconds)
  • Implement retry logic with exponential backoff

Error Handling Best Practices

1. Always Check Status Codes

const response = await fetch(url, options);

if (!response.ok) {
  const error = await response.json();
  console.error('API Error:', error.error);

  // Handle specific error types
  switch (error.error.type) {
    case 'insufficient_credits':
      // Prompt user to upgrade
      break;
    case 'rate_limit_exceeded':
      // Implement backoff
      break;
    default:
      // Generic error handling
  }
}

2. Implement Retry Logic

async function apiCall(url, options, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch(url, options);

      if (response.status === 429) {
        // Rate limited - use exponential backoff
        const retryAfter = response.headers.get('Retry-After');
        await new Promise(resolve =>
          setTimeout(resolve, (retryAfter || 60) * 1000)
        );
        continue;
      }

      if (response.status >= 500) {
        // Server error - retry with backoff
        await new Promise(resolve =>
          setTimeout(resolve, Math.pow(2, i) * 1000)
        );
        continue;
      }

      return response;
    } catch (error) {
      if (i === maxRetries - 1) throw error;
    }
  }
}

3. Log Request IDs

Always log the request_id from error responses for support inquiries:
if (!response.ok) {
  const error = await response.json();
  console.error('[API Error]', {
    request_id: error.error.request_id,
    type: error.error.type,
    detail: error.error.detail
  });
}

4. Handle Validation Errors

if (error.error.type === 'invalid_request') {
  error.error.validation_errors.forEach(validationError => {
    console.log(`Field ${validationError.field}: ${validationError.message}`);
    // Update UI to show field-specific errors
  });
}

Rate Limit Headers

Monitor these headers to avoid hitting rate limits:
const rateLimit = {
  limit: response.headers.get('X-RateLimit-Limit'),
  remaining: response.headers.get('X-RateLimit-Remaining'),
  reset: response.headers.get('X-RateLimit-Reset')
};

if (rateLimit.remaining < 10) {
  console.warn('Approaching rate limit!');
  // Slow down or pause requests
}

Webhook Error Notifications

Configure webhooks to receive notifications about video generation failures:
{
  "id": "evt_xyz789",
  "type": "video.failed",
  "created_at": "2025-11-03T10:35:00Z",
  "data": {
    "id": "batch_abc123",
    "status": "failed",
    "error": {
      "type": "rendering_failed",
      "detail": "Video rendering failed due to invalid asset URL"
    }
  }
}
See Webhooks Guide for setup instructions.

Support

If you encounter persistent errors:
  1. Review relevant documentation sections
  2. Contact stephen@getbluma.com with:
    • Request ID from error response
    • Full error message
    • Steps to reproduce
    • Expected vs actual behavior

Next Steps