Skip to content
Documentation

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/incidents
  • GET /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:

HeaderValue
Access-Control-Allow-Origin*
Access-Control-Allow-MethodsGET, POST, PATCH, DELETE, OPTIONS
Access-Control-Allow-HeadersAuthorization, 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" }
StatuserrorMeaning
400invalid_bodyThe request body failed validation. details lists the failing fields.
401unauthenticatedMissing or invalid bearer token.
403account-specificThe account is blocked. The message carries the reason.
404not_foundNo such resource.
410endpoint-specificThe endpoint has been removed. See the reference.
429rate_limitedRate limited. A Retry-After header gives the seconds to wait.
500internal_errorServer 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.

#Next steps