Duplicates collapse into one issue
ErrorHub strips ids, timestamps, URLs, paths and numbers before it fingerprints an error, so one bug stays one issue however many times it fires.
API-first error tracking
One HTTPS endpoint for every stack, no SDK. Duplicates group into issues, and each one comes with a fix prompt for your coding agent.
Product
Send an error and watch it arrive. The same bug fired a hundred times stays one issue, and a resolved issue that comes back reopens itself. Simulated in your browser; nothing is sent.
InvalidOperationException: Order 42 has no address new
TypeError: Cannot read properties of undefined (reading 'total')
TimeoutError: PDF render timed out regression
One bug, 100 occurrences, one issue. Send more, or resolve an issue and send again.
Why ErrorHub
ErrorHub collects error events over one HTTP API, groups duplicates into issues and alerts you when something is new or comes back. There is one kind of data to send and one flat price.
How it works
There is no SDK to install. Your app sends one JSON document to one endpoint and ErrorHub does the rest. The full contract, every reply code and reporters for six stacks are in the guide Error tracking without an SDK.
Name it. ErrorHub gives you an endpoint, a secret server key and a public browser key that can only submit events.
POST JSON to /api/v1/events with your key in the X-ErrorHub-Key header.
Only the error itself is required. Or paste the project's install prompt into Claude Code, Cursor or
Codex and let the agent write the reporter.
Duplicates roll up into one issue. Paste its fix prompt into your agent, review the diff and mark the issue resolved. If the error returns, ErrorHub reopens it and alerts you.
curl -X POST https://errorhub.dev/api/v1/events \
-H "Content-Type: application/json" \
-H "X-ErrorHub-Key: $ERRORHUB_KEY" \
-d '{
"source": "backend",
"level": "error",
"environment": "production",
"release": "1.4.2",
"exceptionType": "InvalidOperationException",
"exceptionMessage": "Order 42 has no address",
"stackTrace": "at Billing.Checkout.Submit() in Checkout.cs:line 88"
}'
export async function report(error) {
try {
await fetch("https://errorhub.dev/api/v1/events", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-ErrorHub-Key": process.env.ERRORHUB_KEY,
},
body: JSON.stringify({
source: "backend",
level: "error",
environment: process.env.NODE_ENV,
exceptionType: error.name,
exceptionMessage: error.message,
stackTrace: error.stack,
}),
signal: AbortSignal.timeout(3000),
});
} catch {
// Reporting must never break the app.
}
}
import json, os, traceback, urllib.request
def report(error: BaseException) -> None:
event = {
"source": "backend",
"level": "error",
"environment": "production",
"exceptionType": type(error).__name__,
"exceptionMessage": str(error),
"stackTrace": "".join(traceback.format_exception(error)),
}
request = urllib.request.Request(
"https://errorhub.dev/api/v1/events",
data=json.dumps(event).encode(),
headers={
"Content-Type": "application/json",
"X-ErrorHub-Key": os.environ["ERRORHUB_KEY"],
},
)
try:
urllib.request.urlopen(request, timeout=3)
except Exception:
pass # Reporting must never break the app.
static readonly HttpClient Http = new() { Timeout = TimeSpan.FromSeconds(3) };
static async Task ReportAsync(Exception error)
{
try
{
using var request = new HttpRequestMessage(
HttpMethod.Post, "https://errorhub.dev/api/v1/events");
request.Headers.Add(
"X-ErrorHub-Key", Environment.GetEnvironmentVariable("ERRORHUB_KEY"));
request.Content = JsonContent.Create(new
{
source = "backend",
level = "error",
environment = "production",
exceptionType = error.GetType().FullName,
exceptionMessage = error.Message,
stackTrace = error.ToString(),
});
await Http.SendAsync(request);
}
catch
{
// Reporting must never break the app.
}
}
func report(err error) {
event, _ := json.Marshal(map[string]string{
"source": "backend",
"level": "error",
"environment": "production",
"exceptionType": fmt.Sprintf("%T", err),
"exceptionMessage": err.Error(),
"stackTrace": string(debug.Stack()),
})
request, _ := http.NewRequest(http.MethodPost,
"https://errorhub.dev/api/v1/events", bytes.NewReader(event))
request.Header.Set("Content-Type", "application/json")
request.Header.Set("X-ErrorHub-Key", os.Getenv("ERRORHUB_KEY"))
client := &http.Client{Timeout: 3 * time.Second}
if response, err := client.Do(request); err == nil {
response.Body.Close()
}
}
function report(Throwable $error): void
{
$request = curl_init('https://errorhub.dev/api/v1/events');
curl_setopt_array($request, [
CURLOPT_POST => true,
CURLOPT_TIMEOUT => 3,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-ErrorHub-Key: ' . getenv('ERRORHUB_KEY'),
],
CURLOPT_POSTFIELDS => json_encode([
'source' => 'backend',
'level' => 'error',
'environment' => 'production',
'exceptionType' => get_class($error),
'exceptionMessage' => $error->getMessage(),
'stackTrace' => $error->getTraceAsString(),
]),
]);
curl_exec($request);
curl_close($request);
}
HTTP/1.1 202 Accepted
{"id":"0199a3c2-6f1e-7b2a-9c41-5d8e2f0a7b13","status":"accepted"}
Features
One path, built end to end: receive the error, group it, tell you, help you fix it and notice if it comes back.
ErrorHub strips ids, timestamps, URLs, paths and numbers before it fingerprints an error, so one bug stays one issue however many times it fires.
Resolve an issue and move on. If the same error fires again, ErrorHub reopens the issue and sends a regression alert.
Push notifications on your phone or desktop. Warnings and repeats of a known error stay silent, so an alert means something changed.
Every issue comes with a prompt for Claude Code, Cursor, Codex or any agent that reads text: stack trace, request, release and context, marked as data so an error message cannot steer the agent. ErrorHub runs no AI model and never touches your code.
Data and privacy
An error report should help you fix a bug. It should not become a copy of your users' data.
Events and issues live on servers of Hetzner Online GmbH in Germany.
The event format has no field for them, and paths are cut at the first ? or #.
Passwords, keys, tokens and connection strings become [Redacted] on the server.
Events are deleted after 30 days. Issue summaries and counts stay.
These controls support data minimization. They do not make your application compliant with any regulation by themselves. The details are in the Privacy Policy and the Data Processing Agreement.
Pricing
€9 a month, unlimited errors, unlimited projects, unlimited users. Start with 7 days free. Prices exclude VAT.
7 days free
€9per month, excl. VAT
For founders and teams running one app or many.
Email and password, or Google. No card yet.
Enter a card in Stripe's checkout. ErrorHub starts recording your errors at once. Nothing is charged for 7 days.
After 7 days the card is charged €9 plus VAT, every month. Cancel in the dashboard before then and you pay nothing.
FAQ
Something missing? Write to office@errorhub.dev.
ErrorHub is an API-first error tracking service for small software teams: any application that can send an HTTPS request reports errors to one endpoint, and ErrorHub groups duplicates into issues, keeps every project in one inbox and alerts when an error is new or comes back. It does not collect logs, traces, session replays or metrics.
No. ErrorHub has no SDK. Your code sends a JSON document to POST /api/v1/events with the
project key in the X-ErrorHub-Key header. Each project also generates an install prompt,
so a coding agent can write the reporter for you. The guide
Error tracking without an SDK has the full contract
and a reporter for six stacks.
Yes. Each project generates an install prompt that a coding agent can follow to add the reporter, and each issue generates a fix prompt with the stack trace, request, release and environment. Paste either one into Claude Code, Cursor, Codex or any agent that reads text. ErrorHub has no plug-in or MCP server today.
No. ErrorHub runs no AI model and never reads or changes your code. Grouping uses fixed rules: it normalizes the message and hashes it with the exception type and stack frames. The fix prompt is plain text you choose to paste into an agent, and the error data in it is labelled as data, not instructions.
Any language that can make an HTTPS request, including C#, JavaScript, TypeScript, Python, Go, PHP, Java and Ruby. Every event is grouped by exception type and normalized message. Stack-frame grouping is tuned for .NET and JavaScript traces today.
One plan: €9 a month, excluding VAT, with unlimited error events, projects and users and 30 days of event history. It starts with a 7-day free trial. You enter a card to start the trial, nothing is charged for 7 days, and if you cancel before the trial ends you pay nothing. There is no event quota and no overage charge: an exception that happens 10,000 times is 10,000 events and one issue. When a trial or subscription ends, ErrorHub stops accepting new events and hides the text of the stored ones until you subscribe again.
On servers of Hetzner Online GmbH in Germany, in the European Union. Events are deleted when their history window ends, which is 30 days. Issue summaries and counts stay, so you keep the history of each bug.
No. Prices exclude VAT. VAT is added at checkout at the rate of your country. A business in another EU country that enters a valid VAT number is invoiced without VAT under the reverse charge rule. Payments are handled by Stripe.
ErrorHub is built and run by Autrady EOOD, a software company in Varna, Bulgaria, registered under UIC 206828616. The Privacy Policy, the Terms of Service and the Data Processing Agreement are public.
Start free for 7 days
Create a project, send one request and read your first issue. The trial is 7 days, unlimited errors, and you can cancel before it ends.
No sales call. Card required, nothing charged for 7 days. Questions first? Write to office@errorhub.dev