API overview
Authentication, CORS, error codes, and rate limiting for the surface the DiffGuardian desktop app calls.
The /api/v1 surface is what the DiffGuardian desktop app calls. It is documented here so
you can see exactly what the app asks the service for — which is, deliberately, very
little. No endpoint on this surface accepts or returns source code, diffs, prompts, or
AI responses.
This is not a public integration API. It has no published stability guarantee and can change with any desktop release.
#Base URL
https://app.diffguardian.ai
#Authentication
Every endpoint except the public ones below requires a session token from your signed-in account:
GET /api/v1/me HTTP/1.1
Host: app.diffguardian.ai
Authorization: Bearer <session token>
Requests are authenticated from the bearer token only — never from a browser cookie.
Public endpoints need no token:
GET /api/v1/incidentsGET /api/v1/content/{slug}GET /api/health
#CORS
The desktop app is an Electron renderer, so every call is a cross-origin browser request
and a packaged build sends Origin: null. The surface therefore answers preflights with:
| Header | Value |
|---|---|
Access-Control-Allow-Origin | * |
Access-Control-Allow-Methods | GET, POST, PATCH, DELETE, OPTIONS |
Access-Control-Allow-Headers | Authorization, Content-Type, X-App-Version |
Access-Control-Allow-Credentials is deliberately not set. A browser will not attach
a signed-in user's cookies to a cross-site call here, so a hostile page learns nothing it
could not get by calling the API with its own token.
#Errors
Errors are JSON with a stable machine-readable error code:
{ "error": "unauthenticated" }
| Status | error | Meaning |
|---|---|---|
400 | invalid_body | The request body failed validation. details lists the failing fields. |
401 | unauthenticated | Missing or invalid bearer token. |
403 | account-specific | The account is blocked. The message carries the reason. |
404 | not_found | No such resource. |
410 | endpoint-specific | The endpoint has been removed. See the reference. |
429 | rate_limited | Rate limited. A Retry-After header gives the seconds to wait. |
500 | internal_error | Server fault. Carries an errorId — quote it in a support request. |
A 500 response looks like:
{ "error": "internal_error", "errorId": "b1c2d3e4f5a6" }
That errorId correlates directly with the server-side log entry, which is why the app
surfaces it rather than hiding it.
#Rate limiting
Checkout creation is rate limited per account — a small number of attempts per hour. A
limited request returns 429 with Retry-After and has no billing effect.
#Health
GET /api/health reports liveness and database reachability. It returns 200 with
{ "ok": true, "db": "up" } when healthy, and 503 when the database is unreachable —
so an uptime monitor can tell a healthy service from one that is serving but degraded.