Endpoint reference
Every desktop-facing endpoint with its request body, response shape, and error codes.
Every endpoint below is under https://app.diffguardian.ai. See
API overview for authentication, CORS, and the shared error shape.
#Account
#GET /api/v1/me
Your profile and your effective plan. This is the app's only recurring server call — it polls this to keep your plan current.
{
"user": {
"id": "user_123",
"email": "dev@example.com",
"name": "Alex Doe",
"avatarUrl": "https://…",
"tier": "PRO",
"subscriptionStatus": "active",
"subscriptionCurrentPeriodEnd": "2026-09-01T00:00:00.000Z",
"tosAcceptedVersion": 3,
"privacyAcceptedVersion": 2
}
}
tier is your effective plan: PRO if either your own subscription is Pro or you
belong to a team with an active subscription.
tier is the only thing the service reports about what you may use. Which AI providers and
models are available on your plan, which features are gated, and how any limit is metered
are all decided by the app itself, on your machine — there is no server-side vendor
allowlist, model allowlist, budget, or quota to fetch, and no endpoint that would return
one.
#POST /api/v1/me/delete
Permanently deletes your account. Requires an explicit confirmation string so it cannot be triggered by a stray request.
{ "confirmation": "DELETE_MY_ACCOUNT" }
Returns { "success": true }. Anything else in the body returns 400 invalid_body.
See Your account and your data for exactly what is
erased.
#Legal
#GET /api/v1/content/{slug}
Public. Returns the current published version of a legal document. Valid slugs:
tos, privacy, ai-disclaimer, security. Anything else returns 404 not_found.
{
"slug": "privacy",
"title": "Privacy Policy",
"version": 2,
"body": "…",
"updatedAt": "2026-06-14T09:12:00.000Z"
}
#POST /api/v1/legal/accept
Records your acceptance of the current legal document set. The app calls this after the onboarding legal step.
The body is optional — the server records the current published versions authoritatively — but the app sends the versions it actually displayed so acceptance is still recorded correctly if the content service is unreachable:
{ "tosVersion": 3, "privacyVersion": 2 }
Response:
{
"success": true,
"acceptedVersions": { "tos": 3, "privacy": 2, "ai-disclaimer": 1 }
}
One acceptance record is written per document, each stamped with the version and time.
#Service status
#GET /api/v1/incidents
Public. Currently active service incidents, most recent first. The app renders these as a banner.
{
"incidents": [
{
"id": "inc_1",
"title": "Degraded sign-in",
"body": "Sign-in is slower than usual while we fail over.",
"severity": "WARNING",
"startsAt": "2026-08-23T10:00:00.000Z",
"endsAt": null
}
]
}
severity is one of INFO, WARNING, MAJOR, CRITICAL. An incident with a null
endsAt is open-ended. Only incidents whose window contains the current time are
returned.
#Billing
#POST /api/v1/payments/checkout
Creates a hosted checkout session for a personal Pro subscription and returns its URL. The app opens that URL in the system browser.
{ "tier": "PRO", "interval": "month" }
| Field | Required | Notes |
|---|---|---|
tier | yes | Only PRO is purchasable. |
interval | no | month or year. Defaults to month. |
stripePromotionCodeId | no | Applies a promotion code to the session. |
Returns { "url": "https://checkout.stripe.com/…" }.
Rate limited per account — see API overview. Returns
400 tier_not_configured if no price is configured for that tier and cadence.
#POST /api/v1/payments/portal
Returns a billing portal URL for your personal subscription — card, cadence, invoices, cancellation. No body.
Returns { "url": "https://billing.stripe.com/…" }, or 404 no_stripe_customer if you
have never checked out.
#Feedback
#POST /api/v1/feedback/rating
Records a star rating you submitted from the app.
{ "surface": "review-summary", "rating": 4, "comment": "Caught a real bug." }
rating must be 1–5; surface identifies what was rated. Both comment and
context are optional. Returns { "ok": true, "id": "…" }. Out-of-range values return
400 rating_out_of_range.
#POST /api/v1/nps
Records a survey response. One response per account per campaign — a repeat submission updates the existing one rather than adding another.
{ "campaignId": "2026-q3", "score": 9, "comment": "Trace It is the reason I use it." }
score must be 0–10. Returns { "ok": true, "id": "…" }. Out-of-range values return
400 score_out_of_range.
#Removed endpoints
#POST /api/v1/reviewers
Removed. Returns 410 reviewer_sync_removed. Reviewer state used to be mirrored
through DiffGuardian; the app now reads and writes it directly with your code host, so
there is nothing to sync. The route is kept so an older build gets an unambiguous answer
rather than a 404.
#Web-only endpoints
These are called by the DiffGuardian website with a browser session, not by the desktop
app, and are not part of the /api/v1 surface:
| Endpoint | Purpose |
|---|---|
POST /api/team/checkout | Buy Pro seats for an organisation — minimum 5, maximum 500, enforced server-side. Caller must be an organisation admin. |
POST /api/team/portal | Open the billing portal for an organisation's subscription. Admin only. |
See Teams and seats.