API Reference — Email Cleaner & Smart Notifications¶
Official public reference for the HTTP API exposed by the Email Cleaner backend.
This document is intended for: - Frontend developers integrating the UI - External services consuming the API - Test and tooling integrations
All routes below are stable v1 endpoints.
1. Authentication¶
All protected endpoints require a valid app session cookie (session_token).
The cookie is set by the backend after Google OAuth completes:
- GET /auth/google initiates OAuth
- GET /auth/google/callback exchanges the code, stores Google tokens, sets the session cookie, and redirects to ${FRONTEND_ORIGIN}/auth/callback
For API tools, the same JWT can also be sent as Authorization: Bearer <SESSION_TOKEN>.
If the token is missing or invalid, the API will return 401 Unauthorized.
2. Emails API¶
2.1 GET /api/v1/emails¶
Returns the list of Gmail emails with optional filters without any AI processing.
Description¶
- Fetches emails from Gmail.
- Applies optional Gmail query filters.
- No ML classification or suggestions.
Request¶
GET /api/v1/emails HTTP/1.1
Cookie: session_token=<SESSION_TOKEN>
Query Parameters¶
unread(optional, boolean) — Only unread emails.olderThan(optional, integer) — Older than N days.category(optional, string) — Gmail category:promotions,social,updates,forums,primary.minAttachmentSize(optional, integer) — Attachments larger than N MB.pageToken(optional, string) — Gmail pagination token.
Response 200 (example)¶
Notes:
- category on the email is the Gmail category (labels).
- classification on each suggestion is the ML classification label.
{
"emails": [
{
"id": "18c8f6e...",
"from": "facturas@cfe.mx",
"subject": "Your power bill",
"date": "2025-11-18T02:32:11.000Z",
"labels": ["INBOX", "UNREAD"],
"isRead": false,
"attachmentSizeMb": 1.2,
"category": "promotions",
"snippet": "Due on November 15...",
"hasAttachment": false,
"size": 52310
}
],
"nextPageToken": "xyz...",
"total": 25
}
Possible Status Codes¶
- 200 OK – Emails returned successfully.
- 401 Unauthorized – Missing or invalid token.
3. Inbox Actions API¶
3.1 POST /api/v1/inbox/actions¶
Executes direct user-initiated Inbox actions for one or more emails.
Description¶
- Separate from suggestion confirmation.
- Intended for explicit Inbox operations initiated from the frontend Inbox surface.
- Records action history with
details.source = "inbox". - Preserves per-item outcomes even if ActionHistory persistence fails after item execution completes.
Request¶
POST /api/v1/inbox/actions HTTP/1.1
Cookie: session_token=<SESSION_TOKEN>
Content-Type: application/json
Request Body¶
{
"emailIds": ["18c8f6e...", "18c8f7a..."],
"action": "archive"
}
emailIds(array of strings, required) — Email IDs to process.action(string, required) — One of:archive,delete,mark_unread.
Response 200 (example)¶
{
"success": true,
"execution": "partial",
"action": "archive",
"source": "inbox",
"summary": {
"total": 2,
"processed": 1,
"failed": 1
},
"results": [
{ "emailId": "18c8f6e...", "status": "ok" },
{ "emailId": "18c8f7a...", "status": "error", "reason": "not_found" }
]
}
Response rules:
successrepresents request-level execution, not “all items succeeded”.executionis one offull,partial, ornone.resultspreserves one outcome per requested email ID.- If ActionHistory persistence fails after one or more items were already executed, the response still preserves the computed per-item outcomes instead of collapsing everything into
system_error.
Possible Status Codes¶
- 200 OK – Actions processed successfully.
- 400 Bad Request – Invalid payload.
- 401 Unauthorized – Missing or invalid token.
4. Suggestions API¶
3.1 GET /api/v1/suggestions¶
Returns Gmail emails enriched with AI-generated suggestions.
Description¶
- Backend fetches recent emails from Gmail.
- Emails are sent to the ML service.
- The response includes a
suggestionsarray per email.
Request¶
GET /api/v1/suggestions HTTP/1.1
Cookie: session_token=<SESSION_TOKEN>
Response 200 (example)¶
{
"emails": [
{
"id": "18c8f6e...",
"from": "facturas@cfe.mx",
"subject": "Your power bill",
"date": "2025-11-18T02:32:11.000Z",
"isRead": false,
"category": "promotions",
"attachmentSizeMb": 1.2,
"suggestions": [
{
"action": "archive",
"classification": "promotions_old",
"confidence_score": 0.85
}
]
}
]
}
ML Failure Behavior¶
If the ML service is unavailable (timeout, network error, 5xx):
- The endpoint still returns 200 OK.
- Each email will include an empty
suggestionsarray.
Example:
{
"emails": [
{
"id": "18c8f6e...",
"from": "facturas@cfe.mx",
"subject": "Your power bill",
"snippet": "Due on November 15...",
"date": "2025-11-18T02:32:11.000Z",
"suggestions": []
}
]
}
Possible Status Codes¶
- 200 OK – Emails returned successfully (with or without suggestions).
- 401 Unauthorized – Missing or invalid token.
5. Notifications API¶
The Notifications API exposes endpoints to:
- Get a summary of suggested actions
- Confirm actions taken on emails
- Retrieve the history of actions per user
- Consume a timeline of notification events (event store / audit log style)
All routes share:
Cookie: session_token=<SESSION_TOKEN>- Prefix:
/api/v1/notifications/...
5.1 GET /api/v1/notifications/summary¶
Returns an aggregate summary of suggested actions for a time window.
Description¶
- Intended for “overview” dashboards.
- Aggregates counts from
NotificationEventrecords. NotificationEventrecords are created only when generated suggestions reach the publish threshold.
Request¶
GET /api/v1/notifications/summary HTTP/1.1
Cookie: session_token=<SESSION_TOKEN>
Query Parameters¶
period(optional, string) —dailyorweekly. Used to filter the summary window (rolling last 24 hours or rolling last 7 days). Windows are evaluated in UTC over persistedNotificationEvent.createdAtvalues and are inclusive on both boundaries. If omitted, the summary covers all time andwindowStart/windowEndarenull.
Response 200 (example)¶
{
"period": "weekly",
"windowStart": "2026-03-01T10:00:00.000Z",
"windowEnd": "2026-03-08T10:00:00.000Z",
"totalEvents": 4,
"totalSuggestions": 12,
"totalConfirmed": 3,
"suggestedActions": {
"archive": 7,
"delete": 5
},
"confirmedActions": {
"accept": 3
},
"classifications": {
"promotions_old": 6,
"stale_unread": 6
}
}
Possible Status Codes¶
- 200 OK – Summary returned successfully.
- 401 Unauthorized – Missing or invalid token.
5.2 POST /api/v1/notifications/confirm¶
Confirms actions for one or more emails (e.g., accept or reject suggested actions).
Description¶
- Used by the UI when the user confirms or rejects suggested actions from Suggestions.
-
Internally, the backend may:
-
Execute Gmail actions.
- Record entries in the action history.
Request¶
POST /api/v1/notifications/confirm HTTP/1.1
Cookie: session_token=<SESSION_TOKEN>
Content-Type: application/json
Request Body¶
{
"emailIds": ["18c8f6e...", "18c8f7a..."],
"action": "accept"
}
emailIds(array of strings, required) — Email IDs to process.action(string, required) — One of:accept,reject.
Response 200 (example)¶
The schema guarantees:
{
"success": true,
"processed": 2,
"emailIds": ["18c8f6e...", "18c8f7a..."],
"action": "accept",
"data": [
{
"userId": "user-123",
"emailId": "18c8f6e...",
"action": "accept",
"timestamp": "2025-11-18T02:32:11.000Z",
"details": {
"gmailResponse": { "status": "OK" },
"note": "Executed"
}
}
]
}
Note: The internal implementation may include additional fields, but
success,processed,emailIdsandactionare guaranteed by contract.
Possible Status Codes¶
- 200 OK – Actions processed successfully.
- 400 Bad Request – Invalid payload (e.g., missing
emailIdsoraction). - 401 Unauthorized – Missing or invalid token.
5.3 GET /api/v1/notifications/history¶
Returns the history of actions taken on emails for the authenticated user.
Description¶
- Used to display “what has been done” over time.
- Returns a paginated list of action records.
- History may now contain both suggestion-confirm actions and Inbox direct actions, distinguishable through
details.source.
Request¶
GET /api/v1/notifications/history HTTP/1.1
Cookie: session_token=<SESSION_TOKEN>
Query Parameters¶
page(optional, integer, default: 1) — Page number.perPage(optional, integer, default: 20) — Items per page.
Response 200 (example)¶
{
"total": 3,
"page": 1,
"perPage": 20,
"data": [
{
"userId": "user-123",
"emailId": "18c8f6e...",
"action": "accept",
"timestamp": "2025-11-18T02:32:11.000Z",
"details": {
"source": "suggestions",
"gmailResponse": { "status": "OK" },
"note": "Executed"
}
}
]
}
Possible Status Codes¶
- 200 OK – History returned successfully.
- 401 Unauthorized – Missing or invalid token.
5.4 GET /api/v1/notifications/events¶
Lists notification events with pagination. Useful to consume a timeline of system/user events related to notifications.
Description¶
- Supports filtering by
typeand byuserId. - Records are stored with
timestamps: true, socreatedAt/updatedAtare always present and map to Sequelize defaults.
Request¶
GET /api/v1/notifications/events HTTP/1.1
Cookie: session_token=<SESSION_TOKEN>
Query Parameters¶
page(optional, integer, default: 1) — Page number.perPage(optional, integer, default: 20) — Items per page.type(optional, string) — Filter by canonical domain event type string.userId(optional, string) — Filter by user identifier. When omitted, the endpoint falls back to the authenticated user from the session/JWT.
Canonical rule: The type query parameter filters by the canonical domain event type string (e.g., domain.suggestions.generated, domain.suggestions.confirmed). Legacy labels such as NEW_SUGGESTIONS / NEW_SUGGESTIONS_EVENT are not supported in src/** or tests/** and may appear only in documentation under a DEPRECATED section for historical traceability.
Response 200 (example)¶
{
"total": 1,
"page": 1,
"perPage": 20,
"data": [
{
"type": "domain.suggestions.generated",
"userId": "demo-user",
"summary": {
"totalSuggestions": 3,
"sampledEmails": []
},
"createdAt": "2025-11-18T02:32:11.000Z",
"updatedAt": "2025-11-18T02:32:11.000Z"
}
]
}
Possible Status Codes¶
- 200 OK – Events returned successfully.
- 401 Unauthorized – Missing or invalid token.
6. Health Check¶
6.1 GET /api/v1/health¶
Simple health-check endpoint for monitoring and local diagnostics.
Request¶
GET /api/v1/health HTTP/1.1
Response 200 (example)¶
{
"status": "ok"
}
7. Error Summary¶
| Status Code | Meaning | Typical Cause |
|---|---|---|
| 200 | OK | Successful request |
| 400 | Bad Request | Invalid body or query parameters |
| 401 | Unauthorized | Missing or invalid session token |
| 422 | Validation Error (if configured) | Payload does not match expected shape |
| 503 | ML Service Unavailable (internal) | ML failure; suggestions fall back to [] |
Note: When the ML service fails, the API does not return 5xx to the client. It returns a valid 200 response with empty
suggestionsarrays.
8. Developer Notes¶
- Backend uses ECMAScript Modules (ESM).
- Gmail is accessed via internal services, not directly from the client.
- ML integration is abstracted through
mlClient. - Event types are domain strings (e.g.,
domain.suggestions.generated). For the canonical list and payload contracts, seedocs/events_contract.md.
Key configuration:
ML_TIMEOUT_MS=5000
ML_BASE_URL=http://localhost:8000
9. Versioning & Updates¶
- API version: v1 (
/api/v1/...). - Last update: 2025