| layout | default |
|---|---|
| title | API Reference |
| permalink | /docs/API_REFERENCE |
Complete API documentation for Rails Error Dashboard.
- HTTP API - REST endpoints for error logging and management
- Ruby API - Commands, Queries, and Models
- Configuration API - Setup and customization
The Rails Error Dashboard provides HTTP endpoints for error logging and management. These endpoints can be used by mobile apps, frontend applications, or other services to log errors programmatically.
All HTTP endpoints are mounted under /error_dashboard by default (configurable).
https://your-app.com/error_dashboard
The dashboard supports HTTP Basic Authentication:
curl -u username:password https://your-app.com/error_dashboard/errorsConfigure credentials in your initializer:
RailsErrorDashboard.configure do |config|
# Authentication is always required (cannot be disabled)
config.dashboard_username = "admin"
config.dashboard_password = "secure_password"
endAPI endpoints are protected by rate limiting (configurable):
- Dashboard Pages: 300 requests/minute per IP
- API Endpoints: 100 requests/minute per IP
Rate limit exceeded returns 429 Too Many Requests:
{
"error": "Rate limit exceeded. Please try again later."
}Configure rate limits:
RailsErrorDashboard.configure do |config|
config.enable_rate_limiting = true
config.rate_limit_per_minute = 100
endWhile the gem doesn't provide built-in HTTP endpoints for error logging (to allow customization), you can easily create them in your application. See Mobile App Integration Guide for complete examples.
# app/controllers/api/v1/mobile_errors_controller.rb
module Api
module V1
class MobileErrorsController < BaseController
# POST /api/v1/mobile_errors
def create
RailsErrorDashboard::Commands::LogError.call(
error_type: error_params[:error_type],
message: error_params[:message],
backtrace: error_params[:stack]&.split("\n"),
occurred_at: Time.current,
platform: error_params[:platform],
app_version: error_params[:app_version],
user_id: current_user&.id,
request_url: error_params[:url],
ip_address: request.remote_ip,
user_agent: request.user_agent
)
render json: { success: true }, status: :created
rescue => e
render json: { error: e.message }, status: :unprocessable_entity
end
private
def error_params
params.require(:error).permit(
:error_type, :message, :stack, :platform,
:app_version, :url, :component
)
end
end
end
endcurl -X POST https://your-app.com/api/v1/mobile_errors \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"error": {
"error_type": "TypeError",
"message": "Cannot read property of undefined",
"stack": "TypeError: Cannot read property...\n at Component.render",
"platform": "ios",
"app_version": "2.1.0",
"url": "/recordings/new",
"component": "RecordingScreen"
}
}'Success (201 Created):
{
"success": true
}Error (422 Unprocessable Entity):
{
"error": "Validation failed: Message can't be blank"
}These endpoints are used by the web dashboard UI but can also be accessed programmatically.
Get a paginated list of errors with optional filtering.
Endpoint: GET /error_dashboard/errors
Query Parameters:
| Parameter | Type | Description | Example |
|---|---|---|---|
page |
integer | Page number (default: 1) | ?page=2 |
per_page |
integer | Items per page (default: 25) | ?per_page=50 |
platform |
string | Filter by platform | ?platform=iOS |
error_type |
string | Filter by error type | ?error_type=NoMethodError |
severity |
string | Filter by severity | ?severity=critical |
status |
string | Filter by status | ?status=investigating |
assigned_to |
string | Filter by assignee | ?assigned_to=dev@example.com |
priority_level |
integer | Filter by priority (0-4) | ?priority_level=4 |
unresolved |
boolean | Show only unresolved | ?unresolved=true |
hide_snoozed |
boolean | Hide snoozed errors | ?hide_snoozed=true |
hide_muted |
boolean | Hide muted errors | ?hide_muted=true |
search |
string | Search message/backtrace | ?search=payment |
timeframe |
string | Time filter | ?timeframe=today |
sort_by |
string | Sort field | ?sort_by=occurred_at |
sort_direction |
string | Sort direction (asc/desc) | ?sort_direction=desc |
Example:
curl -u admin:password \
"https://your-app.com/error_dashboard/errors?platform=iOS&unresolved=true&per_page=10"Get detailed information about a specific error.
Endpoint: GET /error_dashboard/errors/:id
Example:
curl -u admin:password https://your-app.com/error_dashboard/errors/123Mark an error as resolved.
Endpoint: POST /error_dashboard/errors/:id/resolve
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
resolved_by_name |
string | No | Name of resolver |
resolution_comment |
string | No | Resolution notes |
resolution_reference |
string | No | PR/commit URL |
Example:
curl -X POST -u admin:password \
-d "resolved_by_name=John Doe" \
-d "resolution_comment=Fixed in latest release" \
-d "resolution_reference=https://github.com/org/repo/pull/456" \
https://your-app.com/error_dashboard/errors/123/resolveAssign an error to a team member.
Endpoint: POST /error_dashboard/errors/:id/assign
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
assigned_to |
string | Yes | Email of assignee |
Example:
curl -X POST -u admin:password \
-d "assigned_to=dev@example.com" \
https://your-app.com/error_dashboard/errors/123/assignRemove assignment from an error.
Endpoint: POST /error_dashboard/errors/:id/unassign
Parameters: None required.
Example:
curl -X POST -u admin:password \
https://your-app.com/error_dashboard/errors/123/unassignChange error priority level.
Endpoint: POST /error_dashboard/errors/:id/update_priority
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
priority_level |
integer | Yes | Priority (0-4) |
Priority levels:
0- None1- Low2- Medium3- High4- Critical
Example:
curl -X POST -u admin:password \
-d "priority_level=4" \
https://your-app.com/error_dashboard/errors/123/update_priorityTemporarily hide an error from active view.
Endpoint: POST /error_dashboard/errors/:id/snooze
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
hours |
integer | Yes | Snooze duration in hours |
reason |
string | No | Reason for snoozing |
Example:
curl -X POST -u admin:password \
-d "hours=24" \
-d "reason=Waiting for third-party API fix" \
https://your-app.com/error_dashboard/errors/123/snoozeResume showing a snoozed error (unsnooze before the snooze duration expires).
Endpoint: POST /error_dashboard/errors/:id/unsnooze
Parameters: None required.
Example:
curl -X POST -u admin:password \
https://your-app.com/error_dashboard/errors/123/unsnoozeMute notifications for an error. Muted errors still appear in the dashboard and continue to be tracked, but all notifications (Slack, email, Discord, PagerDuty, webhooks) are suppressed.
Endpoint: POST /error_dashboard/errors/:id/mute
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
muted_by |
string | No | Name of the person muting |
reason |
string | No | Reason for muting (added as comment) |
Example:
curl -X POST -u admin:password \
-d "muted_by=Jane Doe" \
-d "reason=Known scanner noise, safe to ignore" \
https://your-app.com/error_dashboard/errors/123/muteRestore notifications for a muted error.
Endpoint: POST /error_dashboard/errors/:id/unmute
Parameters: None required.
Example:
curl -X POST -u admin:password \
https://your-app.com/error_dashboard/errors/123/unmuteChange error workflow status.
Endpoint: POST /error_dashboard/errors/:id/update_status
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
status |
string | Yes | New status |
comment |
string | No | Status change comment |
Available statuses:
newinvestigatingfixingtestingdeployedclosed
Example:
curl -X POST -u admin:password \
-d "status=investigating" \
-d "comment=Looking into root cause" \
https://your-app.com/error_dashboard/errors/123/update_statusAdd a comment to an error.
Endpoint: POST /error_dashboard/errors/:id/add_comment
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
author_name |
string | Yes | Comment author |
body |
string | Yes | Comment text |
Example:
curl -X POST -u admin:password \
-d "author_name=John Doe" \
-d "body=This appears to be a race condition" \
https://your-app.com/error_dashboard/errors/123/add_commentPerform actions on multiple errors at once.
Endpoint: POST /error_dashboard/errors/batch_action
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
error_ids[] |
array | Yes | Array of error IDs |
action_type |
string | Yes | Action: "resolve" or "delete" |
resolved_by_name |
string | No | For resolve action |
resolution_comment |
string | No | For resolve action |
Example:
curl -X POST -u admin:password \
-d "error_ids[]=123" \
-d "error_ids[]=124" \
-d "error_ids[]=125" \
-d "action_type=resolve" \
-d "resolved_by_name=John Doe" \
-d "resolution_comment=Fixed in batch update" \
https://your-app.com/error_dashboard/errors/batch_actionGet high-level dashboard statistics.
Endpoint: GET /error_dashboard/overview
Returns:
- Total errors (today, week, month)
- Unresolved/resolved counts
- Errors by platform
- Top error types
- Trend data
- Critical alerts
Get detailed analytics data.
Endpoint: GET /error_dashboard/errors/analytics
Query Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
days |
integer | Days of history | 30 |
Example:
curl -u admin:password \
"https://your-app.com/error_dashboard/errors/analytics?days=7"Returns:
- Errors over time
- Errors by type
- Errors by platform
- Errors by hour
- Top affected users
- Resolution rate
- Mobile vs API errors
- MTTR statistics
- Recurring issues
- Release correlation
Compare error rates across platforms.
Endpoint: GET /error_dashboard/errors/platform_comparison
Query Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
days |
integer | Days of history | 7 |
Example:
curl -u admin:password \
"https://your-app.com/error_dashboard/errors/platform_comparison?days=14"Analyze error patterns and correlations.
Endpoint: GET /error_dashboard/errors/correlation
Query Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
days |
integer | Days of history | 30 |
Example:
curl -u admin:password \
"https://your-app.com/error_dashboard/errors/correlation?days=7"View current configuration settings (read-only).
Endpoint: GET /error_dashboard/settings
Parameters: None
Example:
curl -u admin:password \
https://your-app.com/error_dashboard/settingsNote: This endpoint returns HTML by default (web UI). For programmatic access to configuration, use the Ruby API (RailsErrorDashboard.configuration) instead. See Settings Dashboard Guide for details.
View detected swallowed exceptions — exceptions that are raised but silently rescued.
Endpoint: GET /error_dashboard/errors/swallowed_exceptions
Query Parameters:
| Parameter | Type | Description | Example |
|---|---|---|---|
days |
integer | Time range filter (7, 30, 90) | ?days=30 |
Example:
curl -u admin:password \
"https://your-app.com/error_dashboard/errors/swallowed_exceptions?days=30"Requires: config.detect_swallowed_exceptions = true and Ruby 3.3+
View ActionCable channel health aggregated from breadcrumbs.
Endpoint: GET /error_dashboard/errors/actioncable_health_summary
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
days |
integer | 30 | Time range (7, 30, or 90) |
Example:
curl -u admin:password \
"https://your-app.com/error_dashboard/errors/actioncable_health_summary?days=30"Returns: Dashboard page with channel breakdown — actions, transmissions, subscriptions, rejections, error count, sorted by rejections descending.
Requires: config.enable_actioncable_tracking = true and config.enable_breadcrumbs = true
View diagnostic dump history or capture a new dump.
List dumps: GET /error_dashboard/errors/diagnostic_dumps
Capture new dump: POST /error_dashboard/errors/diagnostic_dumps
Parameters (POST):
| Parameter | Type | Required | Description |
|---|---|---|---|
note |
string | No | Optional note to attach to the dump |
Example:
# List dumps
curl -u admin:password \
https://your-app.com/error_dashboard/errors/diagnostic_dumps
# Capture a new dump
curl -X POST -u admin:password \
-d "note=deploy check" \
https://your-app.com/error_dashboard/errors/diagnostic_dumpsRequires: config.enable_diagnostic_dump = true
Rake task alternative: rails error_dashboard:diagnostic_dump NOTE="deploy check"
View Rack Attack event summary (throttle, blocklist, track events).
Endpoint: GET /error_dashboard/errors/rack_attack_summary
Query Parameters:
| Parameter | Type | Description | Example |
|---|---|---|---|
days |
integer | Time range filter (7, 30, 90) | ?days=7 |
Example:
curl -u admin:password \
"https://your-app.com/error_dashboard/errors/rack_attack_summary?days=7"Requires: config.enable_rack_attack_tracking = true and config.enable_breadcrumbs = true
| Code | Description |
|---|---|
200 |
Success |
201 |
Created |
302 |
Redirect (after POST actions) |
401 |
Unauthorized (authentication required) |
404 |
Not Found |
422 |
Unprocessable Entity (validation error) |
429 |
Too Many Requests (rate limit exceeded) |
500 |
Internal Server Error |
// Log error from React/React Native app
async function reportError(error, component) {
try {
const response = await fetch('https://your-app.com/api/v1/mobile_errors', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${authToken}`
},
body: JSON.stringify({
error: {
error_type: error.name,
message: error.message,
stack: error.stack,
platform: Platform.OS, // 'ios' or 'android'
app_version: AppConfig.version,
component: component
}
})
});
const data = await response.json();
return data.success;
} catch (e) {
console.error('Failed to report error:', e);
return false;
}
}
// Usage in React component
try {
// Your code
} catch (error) {
await reportError(error, 'RecordingScreen');
}import Foundation
struct ErrorReport: Codable {
let error: ErrorDetails
}
struct ErrorDetails: Codable {
let errorType: String
let message: String
let stack: String?
let platform: String
let appVersion: String
let component: String?
enum CodingKeys: String, CodingKey {
case errorType = "error_type"
case message
case stack
case platform
case appVersion = "app_version"
case component
}
}
func reportError(_ error: Error, component: String) {
let errorDetails = ErrorDetails(
errorType: String(describing: type(of: error)),
message: error.localizedDescription,
stack: Thread.callStackSymbols.joined(separator: "\n"),
platform: "ios",
appVersion: Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "unknown",
component: component
)
let report = ErrorReport(error: errorDetails)
guard let url = URL(string: "https://your-app.com/api/v1/mobile_errors"),
let jsonData = try? JSONEncoder().encode(report) else {
return
}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("Bearer \(authToken)", forHTTPHeaderField: "Authorization")
request.httpBody = jsonData
URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Failed to report error: \(error)")
}
}.resume()
}import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
@Serializable
data class ErrorReport(val error: ErrorDetails)
@Serializable
data class ErrorDetails(
val error_type: String,
val message: String,
val stack: String?,
val platform: String,
val app_version: String,
val component: String?
)
suspend fun reportError(error: Throwable, component: String) = withContext(Dispatchers.IO) {
val errorDetails = ErrorDetails(
error_type = error::class.simpleName ?: "UnknownError",
message = error.message ?: "No message",
stack = error.stackTraceToString(),
platform = "android",
app_version = BuildConfig.VERSION_NAME,
component = component
)
val report = ErrorReport(errorDetails)
val json = Json.encodeToString(ErrorReport.serializer(), report)
val client = OkHttpClient()
val mediaType = "application/json; charset=utf-8".toMediaType()
val body = json.toRequestBody(mediaType)
val request = Request.Builder()
.url("https://your-app.com/api/v1/mobile_errors")
.addHeader("Authorization", "Bearer $authToken")
.post(body)
.build()
try {
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) {
println("Failed to report error: ${response.code}")
}
}
} catch (e: Exception) {
println("Failed to report error: ${e.message}")
}
}# Log an error
curl -X POST https://your-app.com/api/v1/mobile_errors \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"error": {
"error_type": "NetworkError",
"message": "Failed to fetch user data",
"stack": "NetworkError: Failed to fetch\n at fetchUser (api.js:42)",
"platform": "web",
"app_version": "2.1.0",
"component": "UserProfile"
}
}'
# List errors
curl -u admin:password \
"https://your-app.com/error_dashboard/errors?platform=iOS&unresolved=true"
# Get error details
curl -u admin:password \
https://your-app.com/error_dashboard/errors/123
# Resolve error
curl -X POST -u admin:password \
-d "resolved_by_name=John Doe" \
-d "resolution_comment=Fixed in v2.1.1" \
https://your-app.com/error_dashboard/errors/123/resolveThe Ruby API provides Commands, Queries, and Service objects for programmatic error management within Rails applications.
RailsErrorDashboard.configure do |config|
# See CUSTOMIZATION.md for all options
endLog an error to the dashboard.
RailsErrorDashboard::Commands::LogError.call(
error_type: "NoMethodError",
message: "undefined method 'name' for nil:NilClass",
backtrace: exception.backtrace,
occurred_at: Time.current,
platform: "iOS", # or "Android", "API", "Web"
app_version: "2.1.0",
git_sha: "a3b4c5d6",
user_id: 123,
request_url: "/api/users",
request_params: { id: 1 },
ip_address: "192.168.1.1",
user_agent: "Mozilla/5.0..."
)Mark an error as resolved.
RailsErrorDashboard::Commands::ResolveError.call(
error_id: 123,
resolved_by: "developer@example.com",
resolution_comment: "Fixed in PR #456",
resolution_reference: "https://github.com/org/repo/pull/456"
)Delete multiple errors.
RailsErrorDashboard::Commands::BatchDeleteErrors.call(
error_ids: [1, 2, 3, 4, 5]
)stats = RailsErrorDashboard::Queries::DashboardStats.call
stats[:total_errors] # Total error count
stats[:errors_today] # Errors today
stats[:errors_last_7_days] # Last 7 days
stats[:errors_last_30_days] # Last 30 days
stats[:top_errors] # Top 10 error types
stats[:errors_by_platform] # Grouped by platform
stats[:resolved_count] # Resolved errors
stats[:unresolved_count] # Unresolved errorserrors = RailsErrorDashboard::Queries::ErrorsList.call(
platform: "iOS",
error_type: "NoMethodError",
unresolved: true,
search: "payment"
)similar = RailsErrorDashboard::Queries::SimilarErrors.call(
error_id: 123,
threshold: 0.6, # 60% similarity
limit: 10
)
similar.each do |result|
result[:error] # ErrorLog instance
result[:similarity] # 0.0 - 1.0
endcomparison = RailsErrorDashboard::Queries::PlatformComparison.new(days: 7)
comparison.error_rate_by_platform
comparison.platform_stability_scores
comparison.platform_health_summary("iOS")
comparison.cross_platform_errorscorrelation = RailsErrorDashboard::Queries::ErrorCorrelation.new(days: 30)
correlation.errors_by_version
correlation.problematic_releases
correlation.multi_error_users
correlation.time_correlated_errorserror = RailsErrorDashboard::ErrorLog.find(123)
# Attributes
error.error_type # "NoMethodError"
error.message # Error message
error.backtrace # Stack trace
error.platform # "iOS", "Android", etc.
error.app_version # "2.1.0"
error.occurrence_count # How many times occurred
error.resolved? # Boolean
error.severity # :critical, :high, :medium, :low
# Associations
error.similar_errors(threshold: 0.6)
error.co_occurring_errors(window_minutes: 5)
error.error_cascades(min_probability: 0.5)
error.occurrence_pattern(days: 30)
error.error_bursts(days: 7)# Cyclical patterns
pattern = RailsErrorDashboard::Services::PatternDetector.analyze_cyclical_pattern(
error_type: "NoMethodError",
platform: "iOS",
days: 30
)
pattern[:pattern_type] # :business_hours, :night, :weekend, :uniform
pattern[:pattern_strength] # 0.0 - 1.0
pattern[:peak_hours] # [9, 10, 11, 14, 15]
pattern[:hourly_distribution] # { 0 => 5, 1 => 3, ... }
# Bursts
bursts = RailsErrorDashboard::Services::PatternDetector.detect_bursts(
error_type: "NoMethodError",
platform: "iOS",
days: 7
)result = RailsErrorDashboard::Services::CascadeDetector.call(
lookback_hours: 24
)
result[:detected] # Number of new cascades
result[:updated] # Number of updated cascadesRailsErrorDashboard::Services::BaselineCalculator.calculate_all_baselinesFor more details, see the source code or inline documentation (YARD format).
Models: app/models/rails_error_dashboard/
Commands: lib/rails_error_dashboard/commands/
Queries: lib/rails_error_dashboard/queries/
Services: lib/rails_error_dashboard/services/