API Reference
Account-scoped REST API
A single bearer token gives an integration read access to every site you own or share via teams. Use this API to drive dashboards, AI agents, or anywhere you need cross-site visibility.
1. Authentication
All endpoints require an Authorization: Bearer <token> header.
- Sign in to ErrorVault and open Settings → API Keys → Personal Access Tokens.
- Click Generate token, give it a name (e.g. "Orbit").
- Copy the token value. It is only shown once. Only the SHA-256 hash is stored on the server, so we cannot recover it later.
curl https://error-vault.com/api/v1/projects \ -H "Authorization: Bearer ev_"
Tokens are prefixed with ev_ so they're easy to spot in
code-leak scans. Revoke any token at any time from the same settings page; revoked tokens stop working immediately.
2. Rate limits
120 requests per minute per token. The standard
X-RateLimit-Limit /
X-RateLimit-Remaining headers are returned on every response,
and Retry-After on a 429.
/api/v1/projects
List every site (a.k.a. project) the token's user can access — personal sites and team sites.
Example response
{
"data": [
{
"id": 7,
"name": "Acme Marketing Site",
"url": "https://acme.example.com",
"framework": "wordpress",
"errorCount24h": 12,
"lastErrorAt": "2026-05-02T08:14:51+00:00",
"lastSeenAt": "2026-05-02T09:01:12+00:00",
"healthStatus": "healthy"
},
{
"id": 12,
"name": "Acme Internal API",
"url": "https://api.acme.example.com",
"framework": "laravel",
"errorCount24h": 47,
"lastErrorAt": "2026-05-02T08:59:03+00:00",
"lastSeenAt": "2026-05-02T09:02:00+00:00",
"healthStatus": "warning"
}
]
}
| Field | Type | Notes |
|---|---|---|
| id | int | Pass to {id} on subsequent endpoints |
| name | string | User-set in the portal |
| url | string | Site URL |
| framework | string | wordpress, laravel, other |
| errorCount24h | int | Distinct error groups seen in the last 24 hours |
| lastErrorAt | ISO-8601 \| null | Most recent error timestamp |
| lastSeenAt | ISO-8601 \| null | Most recent any-API-call (heartbeat / error / health) |
| healthStatus | string \| null | healthy / warning / critical |
/api/v1/projects/{id}/errors
List grouped errors for a single project. Cursor-paginated; pass since to poll incrementally.
Query parameters
| Param | Type | Notes |
|---|---|---|
| since | ISO-8601 | Only errors with lastSeen >= since |
| limit | int 1-100 | Page size, default 25 |
| severity | csv | e.g. error,critical,fatal |
| status | csv | new, viewed, fixed, ignored |
| cursor | int | Pass pagination.next_cursor from previous response |
Example response
{
"data": [
{
"id": 1247,
"message": "SQLSTATE[42000]: Syntax error or access violation: 1064 ...",
"stackTrace": "#0 vendor/laravel/framework/src/Illuminate/Database/Connection.php(389): PDO->prepare()\n#1 app/Http/Controllers/OrderController.php(214): ...\n...",
"severity": "critical",
"status": "new",
"count": 14,
"firstSeen": "2026-05-01T22:11:09+00:00",
"lastSeen": "2026-05-02T08:59:03+00:00",
"file": "app/Http/Controllers/OrderController.php",
"line": 214,
"url": "https://acme.example.com/orders/8821",
"groupId": "a3f9e4c2b1d8e6f0a7c5d2e9b4f6a8d1"
}
],
"pagination": { "limit": 25, "next_cursor": 1198 }
}
To poll incrementally, store lastSeen from the most recent error and pass it as since on the next call:
GET /api/v1/projects/12/errors?since=2026-05-02T08:59:03Z&limit=100
/api/v1/projects/{id}/security
Latest completed security scan for a project — overall grade, SSL expiry, security-header snapshot and unified findings list.
Example response
{
"data": {
"sslGrade": "A",
"sslExpiresAt": "2026-08-14",
"score": 87,
"completedAt": "2026-05-02T03:15:42+00:00",
"issues": { "critical": 0, "warning": 2, "info": 1, "passed": 9 },
"headers": {
"Strict-Transport-Security": { "status": "pass", "message": "HSTS present, max-age 31536000" },
"Content-Security-Policy": { "status": "warning", "message": "CSP missing" }
},
"findings": [
{ "category": "ssl", "check": "SSL Certificate",
"severity": "pass", "message": "Certificate valid until 2026-08-14",
"recommendation": null },
{ "category": "vulnerability", "check": "WP Login Bruteforce",
"severity": "warning",
"message": "/wp-login.php reachable without rate limiting",
"recommendation": "Install a rate-limiting plugin" }
]
}
}
When no scan has run yet, data contains
sslGrade: null, empty headers /
findings, and a message field.
6. Error responses
// 401 — missing or bad bearer { "success": false, "error": "Missing Authorization: Bearer header.", "code": "MISSING_TOKEN" } { "success": false, "error": "Invalid or revoked API token.", "code": "INVALID_TOKEN" } // 404 — token has no access to that project { "error": "Project not found or you do not have access.", "code": "NOT_FOUND" } // 422 — bad query params { "error": "Invalid query parameters", "details": { "limit": ["The limit must not be greater than 100."] } } // 429 — rate limit exceeded // Standard Laravel response with X-RateLimit-* and Retry-After headers
Need a token?
Generate one from your account settings.